Update the generator with 1.16 changes
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers;
|
||||
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
@@ -7,42 +8,54 @@ import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||
* @author James Seibel
|
||||
* @version 12-11-2021
|
||||
*/
|
||||
public class VersionConstants implements IVersionConstants {
|
||||
public static final VersionConstants INSTANCE = new VersionConstants();
|
||||
|
||||
|
||||
private VersionConstants() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinimumWorldHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWorldGeneratorSingleThreaded(DistanceGenerationMode distanceGenerationMode) {
|
||||
// We are always asking the server to generate the chunk,
|
||||
// so no use running this stuff multithreaded.
|
||||
return true;
|
||||
/*
|
||||
switch (distanceGenerationMode) {
|
||||
default:
|
||||
case NONE:
|
||||
case BIOME_ONLY:
|
||||
case BIOME_ONLY_SIMULATE_HEIGHT:
|
||||
case SURFACE:
|
||||
case FEATURES:
|
||||
return false;
|
||||
|
||||
case FULL:
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorldGenerationCountPerThread() {
|
||||
return 1;
|
||||
}
|
||||
public class VersionConstants implements IVersionConstants
|
||||
{
|
||||
public static final VersionConstants INSTANCE = new VersionConstants();
|
||||
|
||||
|
||||
private VersionConstants()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinimumWorldHeight()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWorldGeneratorSingleThreaded(DistanceGenerationMode distanceGenerationMode)
|
||||
{
|
||||
// We are always asking the server to generate the chunk,
|
||||
// so no use running this stuff multithreaded.
|
||||
return true;
|
||||
/*
|
||||
switch (distanceGenerationMode) {
|
||||
default:
|
||||
case NONE:
|
||||
case BIOME_ONLY:
|
||||
case BIOME_ONLY_SIMULATE_HEIGHT:
|
||||
case SURFACE:
|
||||
case FEATURES:
|
||||
return false;
|
||||
|
||||
case FULL:
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorldGenerationCountPerThread()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasBatchGenerationImplementation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -25,11 +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.AbstractBatchGenerationEnvionmentWrapper;
|
||||
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.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGeneratorWrapper;
|
||||
|
||||
/**
|
||||
@@ -40,64 +40,65 @@ import com.seibel.lod.common.wrappers.worldGeneration.WorldGeneratorWrapper;
|
||||
*/
|
||||
public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
public static final WrapperFactory INSTANCE = new WrapperFactory();
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos()
|
||||
{
|
||||
return new BlockPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
|
||||
{
|
||||
return new BlockPosWrapper(x,y,z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos()
|
||||
{
|
||||
return new ChunkPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(long xAndZPositionCombined)
|
||||
{
|
||||
return new ChunkPosWrapper(xAndZPositionCombined);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(int x, int z)
|
||||
{
|
||||
return new ChunkPosWrapper(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
|
||||
{
|
||||
return new ChunkPosWrapper(newChunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return new ChunkPosWrapper(blockPos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
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);
|
||||
public static final WrapperFactory INSTANCE = new WrapperFactory();
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos()
|
||||
{
|
||||
return new BlockPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
|
||||
{
|
||||
return new BlockPosWrapper(x, y, z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos()
|
||||
{
|
||||
return new ChunkPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(long xAndZPositionCombined)
|
||||
{
|
||||
return new ChunkPosWrapper(xAndZPositionCombined);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(int x, int z)
|
||||
{
|
||||
return new ChunkPosWrapper(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
|
||||
{
|
||||
return new ChunkPosWrapper(newChunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return new ChunkPosWrapper(blockPos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper);
|
||||
}
|
||||
|
||||
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
|
||||
LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
return new BatchGenerationEnvironment(worldWrapper, newLodBuilder, newLodDimension);
|
||||
}
|
||||
}
|
||||
|
||||
+650
@@ -0,0 +1,650 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2021 Tom Lee (TomTheFurry)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
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.enums.config.LightGenerationMode;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.util.LodThreadFactory;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightGetterAdaptor;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.step.StepBiomes;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.step.StepFeatures;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.step.StepLight;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.step.StepNoise;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.step.StepStructureReference;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.step.StepStructureStart;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.step.StepSurface;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.chunk.UpgradeData;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
|
||||
/*
|
||||
Total: 3.135214124s
|
||||
=====================================
|
||||
Empty Chunks: 0.000558328s
|
||||
StructureStart Step: 0.025177207s
|
||||
StructureReference Step: 0.00189559s
|
||||
Biome Step: 0.13789155s
|
||||
Noise Step: 1.570347555s
|
||||
Surface Step: 0.741238194s
|
||||
Carver Step: 0.000009923s
|
||||
Feature Step: 0.389072425s
|
||||
Lod Generation: 0.269023348s
|
||||
*/
|
||||
|
||||
public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnvionmentWrapper
|
||||
{
|
||||
public static final boolean ENABLE_PERF_LOGGING = true;
|
||||
public static final boolean ENABLE_EVENT_LOGGING = false;
|
||||
public static final boolean ENABLE_LOAD_EVENT_LOGGING = false;
|
||||
//TODO: Make actual proper support for StarLight
|
||||
|
||||
public static class PrefEvent
|
||||
{
|
||||
long beginNano = 0;
|
||||
long emptyNano = 0;
|
||||
long structStartNano = 0;
|
||||
long structRefNano = 0;
|
||||
long biomeNano = 0;
|
||||
long noiseNano = 0;
|
||||
long surfaceNano = 0;
|
||||
long carverNano = 0;
|
||||
long featureNano = 0;
|
||||
long lightNano = 0;
|
||||
long endNano = 0;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "beginNano: " + beginNano + ",\n" +
|
||||
"emptyNano: " + emptyNano + ",\n" +
|
||||
"structStartNano: " + structStartNano + ",\n" +
|
||||
"structRefNano: " + structRefNano + ",\n" +
|
||||
"biomeNano: " + biomeNano + ",\n" +
|
||||
"noiseNano: " + noiseNano + ",\n" +
|
||||
"surfaceNano: " + surfaceNano + ",\n" +
|
||||
"carverNano: " + carverNano + ",\n" +
|
||||
"featureNano: " + featureNano + ",\n" +
|
||||
"lightNano: " + lightNano + ",\n" +
|
||||
"endNano: " + endNano + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public static class PerfCalculator
|
||||
{
|
||||
public static final int SIZE = 50;
|
||||
Rolling totalTime = new Rolling(SIZE);
|
||||
Rolling emptyTime = new Rolling(SIZE);
|
||||
Rolling structStartTime = new Rolling(SIZE);
|
||||
Rolling structRefTime = new Rolling(SIZE);
|
||||
Rolling biomeTime = new Rolling(SIZE);
|
||||
Rolling noiseTime = new Rolling(SIZE);
|
||||
Rolling surfaceTime = new Rolling(SIZE);
|
||||
Rolling carverTime = new Rolling(SIZE);
|
||||
Rolling featureTime = new Rolling(SIZE);
|
||||
Rolling lightTime = new Rolling(SIZE);
|
||||
Rolling lodTime = new Rolling(SIZE);
|
||||
|
||||
public void recordEvent(PrefEvent e)
|
||||
{
|
||||
long preTime = e.beginNano;
|
||||
totalTime.add(e.endNano - preTime);
|
||||
if (e.emptyNano != 0)
|
||||
{
|
||||
emptyTime.add(e.emptyNano - preTime);
|
||||
preTime = e.emptyNano;
|
||||
}
|
||||
if (e.structStartNano != 0)
|
||||
{
|
||||
structStartTime.add(e.structStartNano - preTime);
|
||||
preTime = e.structStartNano;
|
||||
}
|
||||
if (e.structRefNano != 0)
|
||||
{
|
||||
structRefTime.add(e.structRefNano - preTime);
|
||||
preTime = e.structRefNano;
|
||||
}
|
||||
if (e.biomeNano != 0)
|
||||
{
|
||||
biomeTime.add(e.biomeNano - preTime);
|
||||
preTime = e.biomeNano;
|
||||
}
|
||||
if (e.noiseNano != 0)
|
||||
{
|
||||
noiseTime.add(e.noiseNano - preTime);
|
||||
preTime = e.noiseNano;
|
||||
}
|
||||
if (e.surfaceNano != 0)
|
||||
{
|
||||
surfaceTime.add(e.surfaceNano - preTime);
|
||||
preTime = e.surfaceNano;
|
||||
}
|
||||
if (e.carverNano != 0)
|
||||
{
|
||||
carverTime.add(e.carverNano - preTime);
|
||||
preTime = e.carverNano;
|
||||
}
|
||||
if (e.featureNano != 0)
|
||||
{
|
||||
featureTime.add(e.featureNano - preTime);
|
||||
preTime = e.featureNano;
|
||||
}
|
||||
if (e.lightNano != 0)
|
||||
{
|
||||
lightTime.add(e.lightNano - preTime);
|
||||
preTime = e.lightNano;
|
||||
}
|
||||
if (e.endNano != 0)
|
||||
{
|
||||
lodTime.add(e.endNano - preTime);
|
||||
preTime = e.endNano;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Total: " + Duration.ofNanos((long) totalTime.getAverage()) + ", Empty/LoadChunk: "
|
||||
+ Duration.ofNanos((long) emptyTime.getAverage()) + ", StructStart: "
|
||||
+ Duration.ofNanos((long) structStartTime.getAverage()) + ", StructRef: "
|
||||
+ Duration.ofNanos((long) structRefTime.getAverage()) + ", Biome: "
|
||||
+ Duration.ofNanos((long) biomeTime.getAverage()) + ", Noise: "
|
||||
+ Duration.ofNanos((long) noiseTime.getAverage()) + ", Surface: "
|
||||
+ Duration.ofNanos((long) surfaceTime.getAverage()) + ", Carver: "
|
||||
+ Duration.ofNanos((long) carverTime.getAverage()) + ", Feature: "
|
||||
+ Duration.ofNanos((long) featureTime.getAverage()) + ", Light: "
|
||||
+ Duration.ofNanos((long) lightTime.getAverage()) + ", Lod: "
|
||||
+ Duration.ofNanos((long) lodTime.getAverage());
|
||||
}
|
||||
}
|
||||
|
||||
public static final int TIMEOUT_SECONDS = 30;
|
||||
|
||||
//FIXME: Remove this and use the Utils one
|
||||
public static final class GridList<T> extends ArrayList<T> implements List<T>
|
||||
{
|
||||
|
||||
public static class Pos
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public Pos(int xx, int yy)
|
||||
{
|
||||
x = xx;
|
||||
y = yy;
|
||||
}
|
||||
}
|
||||
|
||||
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 T getOffsetOf(int index, int x, int y)
|
||||
{
|
||||
return get(index + x + y * gridSize);
|
||||
}
|
||||
|
||||
public int offsetOf(int index, int x, int y)
|
||||
{
|
||||
return index + x + y * gridSize;
|
||||
}
|
||||
|
||||
public Pos posOf(int index)
|
||||
{
|
||||
return new Pos(index % gridSize, index / gridSize);
|
||||
}
|
||||
|
||||
public int calculateOffset(int x, int y)
|
||||
{
|
||||
return x + y * gridSize;
|
||||
}
|
||||
|
||||
public GridList<T> subGrid(int gridCentreToEdge)
|
||||
{
|
||||
int centreIndex = size() / 2;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=================Generation Step===================
|
||||
|
||||
public final LinkedList<GenerationEvent> events = new LinkedList<GenerationEvent>();
|
||||
public final GlobalParameters params;
|
||||
public final StepStructureStart stepStructureStart = new StepStructureStart(this);
|
||||
public final StepStructureReference stepStructureReference = new StepStructureReference(this);
|
||||
public final StepBiomes stepBiomes = new StepBiomes(this);
|
||||
public final StepNoise stepNoise = new StepNoise(this);
|
||||
public final StepSurface stepSurface = new StepSurface(this);
|
||||
public final StepFeatures stepFeatures = new StepFeatures(this);
|
||||
public final StepLight stepLight = new StepLight(this);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
public static final LodThreadFactory threadFactory = new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY);
|
||||
|
||||
public ExecutorService executors = Executors.newFixedThreadPool(
|
||||
CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads(), threadFactory);
|
||||
|
||||
public void resizeThreadPool(int newThreadCount)
|
||||
{
|
||||
executors = Executors.newFixedThreadPool(newThreadCount,
|
||||
new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY));
|
||||
}
|
||||
|
||||
public boolean tryAddPoint(int px, int pz, int range, Steps target)
|
||||
{
|
||||
int boxSize = range * 2 + 1;
|
||||
int x = Math.floorDiv(px, boxSize) * boxSize + range;
|
||||
int z = Math.floorDiv(pz, boxSize) * boxSize + range;
|
||||
|
||||
for (GenerationEvent event : events)
|
||||
{
|
||||
if (event.tooClose(x, z, range))
|
||||
return false;
|
||||
}
|
||||
// System.out.println(x + ", "+z);
|
||||
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateAllFutures()
|
||||
{
|
||||
// Update all current out standing jobs
|
||||
Iterator<GenerationEvent> iter = events.iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
GenerationEvent event = iter.next();
|
||||
if (event.isCompleted())
|
||||
{
|
||||
try
|
||||
{
|
||||
event.join();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
while (e.getCause() != null)
|
||||
{
|
||||
e = e.getCause();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS))
|
||||
{
|
||||
ClientApi.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
|
||||
ClientApi.LOGGER.info("Dump PrefEvent: " + event.pEvent);
|
||||
try
|
||||
{
|
||||
if (!event.terminate())
|
||||
ClientApi.LOGGER.error("Failed to terminate the stuck generation event!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim)
|
||||
{
|
||||
super(serverlevel, lodBuilder, lodDim);
|
||||
ClientApi.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
|
||||
params = new GlobalParameters((ServerLevel) ((WorldWrapper) serverlevel).getWorld(), lodBuilder, lodDim);
|
||||
}
|
||||
|
||||
public void startLoadingAllRegionsFromFile(LodDimension lodDim)
|
||||
{
|
||||
ServerLevel level = params.level;
|
||||
level.getChunkSource();
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine)
|
||||
{
|
||||
CompoundTag chunkData = null;
|
||||
try
|
||||
{
|
||||
chunkData = level.getChunkSource().chunkMap.readChunk(chunkPos);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ClientApi.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||
}
|
||||
if (chunkData == null)
|
||||
{
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void generateLodFromList(GenerationEvent e)
|
||||
{
|
||||
if (ENABLE_EVENT_LOGGING)
|
||||
ClientApi.LOGGER.info("Lod Generate Event: " + e.pos);
|
||||
e.pEvent.beginNano = System.nanoTime();
|
||||
GridList<ChunkAccess> referencedChunks;
|
||||
DistanceGenerationMode generationMode;
|
||||
LightedWorldGenRegion region;
|
||||
WorldGenLevelLightEngine lightEngine;
|
||||
LightGetterAdaptor adaptor;
|
||||
|
||||
try
|
||||
{
|
||||
adaptor = new LightGetterAdaptor(params.level);
|
||||
lightEngine = new WorldGenLevelLightEngine(adaptor);
|
||||
|
||||
int cx = e.pos.x;
|
||||
int cy = e.pos.z;
|
||||
int rangeEmpty = e.range + 1;
|
||||
GridList<ChunkAccess> chunks = new GridList<ChunkAccess>(rangeEmpty);
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
EmptyChunkGenerator generator = (int x, int z) ->
|
||||
{
|
||||
ChunkPos chunkPos = new ChunkPos(x, z);
|
||||
ChunkAccess target = null;
|
||||
try
|
||||
{
|
||||
target = loadOrMakeChunk(chunkPos, params.level, lightEngine);
|
||||
}
|
||||
catch (RuntimeException e2)
|
||||
{
|
||||
// Continue...
|
||||
e2.printStackTrace();
|
||||
}
|
||||
if (target == null)
|
||||
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY, params.level,
|
||||
params.biomes, null);
|
||||
return target;
|
||||
};
|
||||
|
||||
for (int oy = -rangeEmpty; oy <= rangeEmpty; oy++)
|
||||
{
|
||||
for (int ox = -rangeEmpty; ox <= rangeEmpty; ox++)
|
||||
{
|
||||
ChunkAccess target = generator.generate(cx + ox, cy + oy);
|
||||
chunks.add(target);
|
||||
}
|
||||
}
|
||||
e.pEvent.emptyNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
region = new LightedWorldGenRegion(params.level, lightEngine, e.tParam.structFeat, chunks, ChunkStatus.STRUCTURE_STARTS, rangeEmpty, e.lightMode, generator);
|
||||
adaptor.setRegion(region);
|
||||
referencedChunks = chunks.subGrid(e.range);
|
||||
referencedChunks = generateDirect(e, referencedChunks, e.target, region);
|
||||
|
||||
}
|
||||
catch (StepStructureStart.StructStartCorruptedException f)
|
||||
{
|
||||
e.tParam.markAsInvalid();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.target)
|
||||
{
|
||||
case Empty:
|
||||
case StructureStart:
|
||||
case StructureReference:
|
||||
generationMode = DistanceGenerationMode.NONE;
|
||||
break;
|
||||
case Biomes:
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY;
|
||||
case Noise:
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Surface:
|
||||
case Carvers:
|
||||
generationMode = DistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Features:
|
||||
generationMode = DistanceGenerationMode.FEATURES;
|
||||
break;
|
||||
case Light:
|
||||
case LiquidCarvers:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int oy = -e.range; oy <= e.range; oy++)
|
||||
{
|
||||
for (int ox = -e.range; ox <= e.range; ox++)
|
||||
{
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkAccess target = referencedChunks.get(targetIndex);
|
||||
target.setLightCorrect(true);
|
||||
if (target instanceof LevelChunk)
|
||||
((LevelChunk) target).setClientLightReady(true);
|
||||
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
|
||||
boolean isPartial = target.isOldNoiseGeneration();
|
||||
if (isFull)
|
||||
{
|
||||
if (ENABLE_LOAD_EVENT_LOGGING)
|
||||
ClientApi.LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
new LodBuilderConfig(DistanceGenerationMode.FULL), true);
|
||||
}
|
||||
else if (isPartial)
|
||||
{
|
||||
if (ENABLE_LOAD_EVENT_LOGGING)
|
||||
ClientApi.LOGGER.info("Detected old existing chunk at {}", target.getPos());
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
new LodBuilderConfig(generationMode), true);
|
||||
}
|
||||
else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE)
|
||||
{
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
LodBuilderConfig.getFillVoidConfig(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
new LodBuilderConfig(generationMode), true);
|
||||
}
|
||||
if (e.lightMode == LightGenerationMode.FANCY || isFull)
|
||||
{
|
||||
lightEngine.retainData(target.getPos(), false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
e.pEvent.endNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (ENABLE_PERF_LOGGING)
|
||||
{
|
||||
e.tParam.perf.recordEvent(e.pEvent);
|
||||
ClientApi.LOGGER.info(e.tParam.perf);
|
||||
}
|
||||
}
|
||||
|
||||
public GridList<ChunkAccess> generateDirect(GenerationEvent e, GridList<ChunkAccess> subRange, Steps step,
|
||||
LightedWorldGenRegion region)
|
||||
{
|
||||
try
|
||||
{
|
||||
subRange.forEach((chunk) ->
|
||||
{
|
||||
if (chunk instanceof ProtoChunk)
|
||||
{
|
||||
((ProtoChunk) chunk).setLightEngine(region.getLightEngine());
|
||||
region.getLightEngine().retainData(chunk.getPos(), true);
|
||||
}
|
||||
});
|
||||
if (step == Steps.Empty)
|
||||
return subRange;
|
||||
stepStructureStart.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.structStartNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.StructureStart)
|
||||
return subRange;
|
||||
stepStructureReference.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.structRefNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.StructureReference)
|
||||
return subRange;
|
||||
stepBiomes.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.biomeNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.Biomes)
|
||||
return subRange;
|
||||
stepNoise.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.noiseNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.Noise)
|
||||
return subRange;
|
||||
stepSurface.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.surfaceNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.Surface)
|
||||
return subRange;
|
||||
if (step == Steps.Carvers)
|
||||
return subRange;
|
||||
stepFeatures.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.featureNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
return subRange;
|
||||
}
|
||||
finally
|
||||
{
|
||||
switch (region.lightMode)
|
||||
{
|
||||
case FANCY:
|
||||
stepLight.generateGroup(region.getLightEngine(), subRange);
|
||||
break;
|
||||
case FAST:
|
||||
subRange.forEach((p) ->
|
||||
{
|
||||
if (p instanceof ProtoChunk)
|
||||
((ProtoChunk) p).setLightCorrect(true);
|
||||
});
|
||||
break;
|
||||
}
|
||||
e.pEvent.lightNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
public interface EmptyChunkGenerator
|
||||
{
|
||||
ChunkAccess generate(int x, int z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEventCount() {
|
||||
return events.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
ClientApi.LOGGER.info("Batch Chunk Generator shutting down...");
|
||||
executors.shutdownNow();
|
||||
try {
|
||||
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-10
@@ -54,7 +54,8 @@ public class ChunkLoader
|
||||
private static final String BLOCK_TICKS_TAG = "block_ticks";
|
||||
private static final String FLUID_TICKS_TAG = "fluid_ticks";
|
||||
|
||||
private static BlendingData readBlendingData(CompoundTag chunkData) {
|
||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||
{
|
||||
BlendingData blendingData = null;
|
||||
if (chunkData.contains("blending_data", 10))
|
||||
{
|
||||
@@ -65,7 +66,8 @@ public class ChunkLoader
|
||||
return blendingData;
|
||||
}
|
||||
|
||||
private static LevelChunkSection[] readSections(LevelAccessor level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData) {
|
||||
private static LevelChunkSection[] readSections(LevelAccessor level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
|
||||
{
|
||||
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
|
||||
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
||||
@@ -98,7 +100,8 @@ public class ChunkLoader
|
||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||
}
|
||||
|
||||
if (!isLightOn) continue;
|
||||
if (!isLightOn)
|
||||
continue;
|
||||
|
||||
if (tagSection.contains("BlockLight", 7))
|
||||
lightEngine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, sectionYPos), new DataLayer(tagSection.getByteArray("BlockLight")), true);
|
||||
@@ -108,7 +111,8 @@ public class ChunkLoader
|
||||
return chunkSections;
|
||||
}
|
||||
|
||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData) {
|
||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||
{
|
||||
@@ -147,7 +151,7 @@ public class ChunkLoader
|
||||
for (String string : compoundTag2.getAllKeys())
|
||||
{
|
||||
String string2 = string.toLowerCase(Locale.ROOT);
|
||||
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||
if (structureFeature == null)
|
||||
{
|
||||
LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", (Object) string2, (Object) chunkPos);
|
||||
@@ -167,14 +171,16 @@ public class ChunkLoader
|
||||
return map;
|
||||
}
|
||||
|
||||
private static void readStructures(WorldGenLevel level, LevelChunk chunk, CompoundTag chunkData) {
|
||||
private static void readStructures(WorldGenLevel level, LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
CompoundTag tagStructures = chunkData.getCompound("structures");
|
||||
chunk.setAllStarts(
|
||||
unpackStructureStart(StructurePieceSerializationContext.fromLevel(level.getLevel()), tagStructures, level.getSeed()));
|
||||
chunk.setAllReferences(unpackStructureReferences(chunk.getPos(), tagStructures));
|
||||
}
|
||||
|
||||
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData) {
|
||||
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
|
||||
for (int n = 0; n < tagPostProcessings.size(); ++n)
|
||||
{
|
||||
@@ -185,7 +191,7 @@ public class ChunkLoader
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static ChunkStatus.ChunkType readChunkType(CompoundTag compoundTag)
|
||||
{
|
||||
return ChunkStatus.byName(compoundTag.getString("Status")).getChunkType();
|
||||
@@ -203,11 +209,13 @@ public class ChunkLoader
|
||||
|
||||
ChunkStatus.ChunkType chunkType = readChunkType(chunkData);
|
||||
BlendingData blendingData = readBlendingData(chunkData);
|
||||
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise())) return null;
|
||||
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise()))
|
||||
return null;
|
||||
|
||||
// Prepare the light engine
|
||||
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
||||
if (isLightOn) level.getLightEngine().retainData(chunkPos, true);
|
||||
if (isLightOn)
|
||||
level.getLightEngine().retainData(chunkPos, true);
|
||||
|
||||
// Read params for making the LevelChunk
|
||||
UpgradeData upgradeData = chunkData.contains(TAG_UPGRADE_DATA, 10)
|
||||
|
||||
-320
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2021 Tom Lee (TomTheFurry) & James Seibel (Original code)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGenerationStep.Steps;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.GenerationPriority;
|
||||
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.LodUtil;
|
||||
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;
|
||||
|
||||
public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWrapper {
|
||||
|
||||
public static final boolean ENABLE_GENERATOR_STATS_LOGGING = false;
|
||||
|
||||
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 int previousThreadCount = CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads();
|
||||
|
||||
private int estimatedSampleNeeded = 128;
|
||||
private int estimatedPointsToQueue = 1;
|
||||
|
||||
public ExperimentalGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
|
||||
super(newLodBuilder, newLodDimension, worldWrapper);
|
||||
MC.sendChatMessage("WARNING: You are currently using Distant Horizon's Experimental Chunk Pre-Generator!");
|
||||
MC.sendChatMessage("The generation mode: Feature mode is not recommended for < 8GB RAM");
|
||||
MC.sendChatMessage("Stuff may break at any time!");
|
||||
generationGroup = new WorldGenerationStep(((WorldWrapper) worldWrapper).getServerWorld(), newLodBuilder,
|
||||
newLodDimension);
|
||||
ClientApi.LOGGER.info("1.18 Experimental Chunk Generator initialized");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void queueGenerationRequests(LodDimension lodDim, LodBuilder lodBuilder) {
|
||||
if (lodDim != targetLodDim) {
|
||||
stop();
|
||||
WorldWrapper dim = (WorldWrapper) LodUtil.getServerWorldFromDimension(lodDim.dimension);
|
||||
generationGroup = new WorldGenerationStep(dim.getServerWorld(), lodBuilder, lodDim);
|
||||
targetLodDim = lodDim;
|
||||
ClientApi.LOGGER.info("1.18 Experimental Chunk Generator reinitialized");
|
||||
}
|
||||
|
||||
DistanceGenerationMode mode = CONFIG.client().worldGenerator().getDistanceGenerationMode();
|
||||
int newThreadCount = CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads();
|
||||
if (newThreadCount != previousThreadCount) {
|
||||
generationGroup.resizeThreadPool(newThreadCount);
|
||||
previousThreadCount = newThreadCount;
|
||||
}
|
||||
if (estimatedPointsToQueue < newThreadCount) estimatedPointsToQueue = newThreadCount;
|
||||
|
||||
GenerationPriority priority = CONFIG.client().worldGenerator().getGenerationPriority();
|
||||
if (priority == GenerationPriority.AUTO)
|
||||
priority = MC.hasSinglePlayerServer() ? GenerationPriority.FAR_FIRST : GenerationPriority.NEAR_FIRST;
|
||||
|
||||
generationGroup.updateAllFutures();
|
||||
if (!MC.hasSinglePlayerServer())
|
||||
return;
|
||||
int eventsCount = generationGroup.events.size();
|
||||
// If we still all jobs running, return.
|
||||
if (eventsCount >= estimatedPointsToQueue) {
|
||||
estimatedPointsToQueue--;
|
||||
if (estimatedPointsToQueue < newThreadCount) estimatedPointsToQueue = newThreadCount;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final int targetToGenerate = estimatedPointsToQueue - eventsCount;
|
||||
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, priority, mode);
|
||||
|
||||
if (eventsCount == 0 && posToGenerate.getNumberOfPos()>=estimatedSampleNeeded) {
|
||||
estimatedPointsToQueue++;
|
||||
if (estimatedPointsToQueue > newThreadCount*10) estimatedPointsToQueue = newThreadCount*10;
|
||||
}
|
||||
|
||||
//ClientApi.LOGGER.info("PosToGenerate: {}", posToGenerate);
|
||||
|
||||
// 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.
|
||||
Steps targetStep;
|
||||
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;
|
||||
// TODO!
|
||||
default:
|
||||
assert false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ENABLE_GENERATOR_STATS_LOGGING)
|
||||
ClientApi.LOGGER.info("WorldGen. Near:"+posToGenerate.getNumberOfNearPos()+" Far:"+posToGenerate.getNumberOfFarPos());
|
||||
if (priority == GenerationPriority.FAR_FIRST || priority == GenerationPriority.BALANCED) {
|
||||
|
||||
int nearCount = posToGenerate.getNumberOfNearPos();
|
||||
int farCount = posToGenerate.getNumberOfFarPos();
|
||||
if (ENABLE_GENERATOR_STATS_LOGGING)
|
||||
ClientApi.LOGGER.info("WorldGen. Near:"+nearCount+" Far:"+farCount);
|
||||
int maxIteration = Math.max(nearCount, farCount);
|
||||
for (int i = 0; i < maxIteration; i++) {
|
||||
|
||||
// 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));
|
||||
int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize;
|
||||
if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep)) {
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
|
||||
// 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));
|
||||
int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize;
|
||||
if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep)) {
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
int farCount = posToGenerate.getNumberOfFarPos();
|
||||
for (int i = 0; i < farCount; i++) {
|
||||
|
||||
// We have nearPos to go though
|
||||
if (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));
|
||||
int genSize = detailLevel != 0 ? 0 : generationGroupSize;
|
||||
if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep)) {
|
||||
toGenerate--;
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Only do near gen if toGenerate is non 0 and that we have requested all samples we can get.
|
||||
if (toGenerate > 0 && estimatedSampleNeeded > posToGenerate.getNumberOfPos()) {
|
||||
int nearCount = posToGenerate.getNumberOfNearPos();
|
||||
for (int i = 0; i < nearCount; i++) {
|
||||
// We have farPos to go though
|
||||
if (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));
|
||||
int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize;
|
||||
if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep)) {
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
int nearCount = posToGenerate.getNumberOfNearPos();
|
||||
for (int i = 0; i < nearCount; i++) {
|
||||
|
||||
// We have nearPos to go though
|
||||
if (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));
|
||||
int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize;
|
||||
if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep)) {
|
||||
toGenerate--;
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Only do far gen if toGenerate is non 0 and that we have requested all samples we can get.
|
||||
if (toGenerate > 0 && estimatedSampleNeeded > posToGenerate.getNumberOfPos()) {
|
||||
int farCount = posToGenerate.getNumberOfFarPos();
|
||||
for (int i = 0; i < farCount; i++) {
|
||||
// We have farPos to go though
|
||||
if (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));
|
||||
int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize;
|
||||
if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep)) {
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetToGenerate != toGenerate && ENABLE_GENERATOR_STATS_LOGGING) {
|
||||
if (toGenerate <= 0) {
|
||||
ClientApi.LOGGER.info(
|
||||
"WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of " + estimatedSampleNeeded
|
||||
+ " points, started all targeted " + targetToGenerate + " generations.");
|
||||
} else {
|
||||
ClientApi.LOGGER.info("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;
|
||||
if (ENABLE_GENERATOR_STATS_LOGGING)
|
||||
ClientApi.LOGGER.info("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;
|
||||
if (ENABLE_GENERATOR_STATS_LOGGING)
|
||||
ClientApi.LOGGER.info("WorldGenerator: Decreasing estimatedSampleNeeeded to " + estimatedSampleNeeded);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
ClientApi.LOGGER.info("1.18 Experimental Chunk Generator shutting down...");
|
||||
generationGroup.executors.shutdownNow();
|
||||
try {
|
||||
if (!generationGroup.executors.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
ClientApi.LOGGER.error("1.18 Experimental Chunk Generator shutdown failed! Ignoring child threads...");
|
||||
}
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
|
||||
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
|
||||
//======================= Main Event class======================
|
||||
public final class GenerationEvent
|
||||
{
|
||||
static private final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
private static int generationFutureDebugIDs = 0;
|
||||
final ThreadedParameters tParam;
|
||||
final ChunkPos pos;
|
||||
final int range;
|
||||
final Future<?> future;
|
||||
long nanotime;
|
||||
final int id;
|
||||
final Steps target;
|
||||
final LightGenerationMode lightMode;
|
||||
final PrefEvent pEvent = new PrefEvent();
|
||||
|
||||
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target)
|
||||
{
|
||||
nanotime = System.nanoTime();
|
||||
this.pos = pos;
|
||||
this.range = range;
|
||||
id = generationFutureDebugIDs++;
|
||||
this.target = target;
|
||||
this.tParam = ThreadedParameters.getOrMake(generationGroup.params);
|
||||
LightGenerationMode mode = CONFIG.client().worldGenerator().getLightGenerationMode();
|
||||
|
||||
this.lightMode = mode;
|
||||
|
||||
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 boolean terminate()
|
||||
{
|
||||
future.cancel(true);
|
||||
ClientApi.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
|
||||
BatchGenerationEnvironment.threadFactory.dumpAllThreadStacks();
|
||||
return future.isCancelled();
|
||||
}
|
||||
|
||||
public void join()
|
||||
{
|
||||
try
|
||||
{
|
||||
future.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tooClose(int cx, int cz, int cr)
|
||||
{
|
||||
int distX = Math.abs(cx - pos.x);
|
||||
int distZ = Math.abs(cz - pos.z);
|
||||
int minRange = cr + range + 1; // Need one to account for the center
|
||||
minRange += 1 + 1; // Account for required empty chunks
|
||||
return distX < minRange && distZ < minRange;
|
||||
}
|
||||
|
||||
public void refreshTimeout()
|
||||
{
|
||||
nanotime = System.nanoTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return id + ":" + range + "@" + pos + "(" + target + ")";
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.storage.WorldData;
|
||||
|
||||
public final class GlobalParameters
|
||||
{
|
||||
public final ChunkGenerator generator;
|
||||
public final StructureManager structures;
|
||||
public final BiomeManager biomeManager;
|
||||
public final WorldGenSettings worldGenSettings;
|
||||
public final ThreadedLevelLightEngine lightEngine;
|
||||
public final LodBuilder lodBuilder;
|
||||
public final LodDimension lodDim;
|
||||
public final Registry<Biome> biomes;
|
||||
public final RegistryAccess registry;
|
||||
public final long worldSeed;
|
||||
public final ChunkScanAccess chunkScanner;
|
||||
public final ServerLevel level; // TODO: Figure out a way to remove this. Maybe ClientLevel also works?
|
||||
public final DataFixer fixerUpper;
|
||||
|
||||
public GlobalParameters(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim)
|
||||
{
|
||||
this.lodBuilder = lodBuilder;
|
||||
this.lodDim = lodDim;
|
||||
this.level = level;
|
||||
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();
|
||||
biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
|
||||
structures = server.getStructureManager();
|
||||
generator = level.getChunkSource().getGenerator();
|
||||
chunkScanner = level.getChunkSource().chunkScanner();
|
||||
fixerUpper = server.getFixerUpper();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
//FIXME: Move this outside the WorldGenerationStep thingy
|
||||
public class Rolling
|
||||
{
|
||||
|
||||
private final int size;
|
||||
private double total = 0d;
|
||||
private int index = 0;
|
||||
private final double[] samples;
|
||||
|
||||
public Rolling(int size)
|
||||
{
|
||||
this.size = size;
|
||||
samples = new double[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
samples[i] = 0d;
|
||||
}
|
||||
|
||||
public void add(double x)
|
||||
{
|
||||
total -= samples[index];
|
||||
samples[index] = x;
|
||||
total += x;
|
||||
if (++index == size)
|
||||
index = 0; // cheaper than modulus
|
||||
}
|
||||
|
||||
public double getAverage()
|
||||
{
|
||||
return total / size;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PerfCalculator;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||||
|
||||
public final class ThreadedParameters
|
||||
{
|
||||
private static final ThreadLocal<ThreadedParameters> localParam = new ThreadLocal<ThreadedParameters>();
|
||||
final ServerLevel level;
|
||||
public WorldGenStructFeatManager structFeat;
|
||||
public final StructureCheck structCheck;
|
||||
boolean isValid = true;
|
||||
public final PerfCalculator perf = new PerfCalculator();
|
||||
|
||||
public static ThreadedParameters getOrMake(GlobalParameters param)
|
||||
{
|
||||
ThreadedParameters tParam = localParam.get();
|
||||
if (tParam != null && tParam.isValid && tParam.level == param.level)
|
||||
return tParam;
|
||||
tParam = new ThreadedParameters(param);
|
||||
localParam.set(tParam);
|
||||
return tParam;
|
||||
}
|
||||
|
||||
public void markAsInvalid()
|
||||
{
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
private ThreadedParameters(GlobalParameters param)
|
||||
{
|
||||
level = param.level;
|
||||
structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures,
|
||||
param.level.dimension(), param.generator, level, param.generator.getBiomeSource(), param.worldSeed,
|
||||
param.fixerUpper);
|
||||
structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings, null, structCheck);
|
||||
}
|
||||
|
||||
public void makeStructFeat(WorldGenLevel genLevel, WorldGenSettings worldGenSettings)
|
||||
{
|
||||
structFeat = new WorldGenStructFeatManager(level, worldGenSettings, genLevel, structCheck);
|
||||
}
|
||||
}
|
||||
-1432
File diff suppressed because it is too large
Load Diff
+88
-84
@@ -1,3 +1,4 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
@@ -30,65 +31,67 @@ import net.minecraft.world.level.chunk.*;
|
||||
*/
|
||||
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
|
||||
{
|
||||
public final ServerLevel serverWorld;
|
||||
public final LodDimension lodDim;
|
||||
public final LodBuilder lodBuilder;
|
||||
|
||||
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
super(newLodBuilder, newLodDimension, worldWrapper);
|
||||
|
||||
lodBuilder = newLodBuilder;
|
||||
lodDim = newLodDimension;
|
||||
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
|
||||
}
|
||||
|
||||
/** takes about 2-5 ms */
|
||||
@Override
|
||||
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), generationMode);
|
||||
}
|
||||
|
||||
/** takes about 10 - 20 ms */
|
||||
@Override
|
||||
public void generateSurface(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.SURFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* takes about 15 - 20 ms
|
||||
*/
|
||||
@Override
|
||||
public void generateFeatures(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FEATURES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates using MC's ServerWorld.
|
||||
* <p>
|
||||
* on pre generated chunks 0 - 1 ms <br>
|
||||
* on un generated chunks 0 - 50 ms <br>
|
||||
* with the median seeming to hover around 15 - 30 ms <br>
|
||||
* and outliers in the 100 - 200 ms range <br>
|
||||
* <p>
|
||||
* Note this should not be multithreaded and does cause server/simulation lag
|
||||
* (Higher lag for generating than loading)
|
||||
*/
|
||||
@Override
|
||||
public void generateFull(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FULL);
|
||||
}
|
||||
|
||||
private void generate(int chunkX, int chunkZ, DistanceGenerationMode generationMode) {
|
||||
|
||||
// long t = System.nanoTime();
|
||||
|
||||
ChunkStatus targetStatus;
|
||||
switch (generationMode) {
|
||||
public final ServerLevel serverWorld;
|
||||
public final LodDimension lodDim;
|
||||
public final LodBuilder lodBuilder;
|
||||
|
||||
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
super(newLodBuilder, newLodDimension, worldWrapper);
|
||||
|
||||
lodBuilder = newLodBuilder;
|
||||
lodDim = newLodDimension;
|
||||
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
|
||||
}
|
||||
|
||||
/** takes about 2-5 ms */
|
||||
@Override
|
||||
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), generationMode);
|
||||
}
|
||||
|
||||
/** takes about 10 - 20 ms */
|
||||
@Override
|
||||
public void generateSurface(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.SURFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* takes about 15 - 20 ms
|
||||
*/
|
||||
@Override
|
||||
public void generateFeatures(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FEATURES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates using MC's ServerWorld.
|
||||
* <p>
|
||||
* on pre generated chunks 0 - 1 ms <br>
|
||||
* on un generated chunks 0 - 50 ms <br>
|
||||
* with the median seeming to hover around 15 - 30 ms <br>
|
||||
* and outliers in the 100 - 200 ms range <br>
|
||||
* <p>
|
||||
* Note this should not be multithreaded and does cause server/simulation lag
|
||||
* (Higher lag for generating than loading)
|
||||
*/
|
||||
@Override
|
||||
public void generateFull(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FULL);
|
||||
}
|
||||
|
||||
private void generate(int chunkX, int chunkZ, DistanceGenerationMode generationMode)
|
||||
{
|
||||
|
||||
// long t = System.nanoTime();
|
||||
|
||||
ChunkStatus targetStatus;
|
||||
switch (generationMode)
|
||||
{
|
||||
case BIOME_ONLY:
|
||||
targetStatus = ChunkStatus.BIOMES;
|
||||
break;
|
||||
@@ -111,39 +114,40 @@ public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
|
||||
|
||||
// The bool=true means that we wants to generate chunk, and that the returned ChunkAccess must not be null
|
||||
ChunkAccess ca = serverWorld.getChunkSource().getChunk(chunkX, chunkZ, targetStatus, true);
|
||||
if (ca == null) throw new RuntimeException("This should NEVER be null due to bool being true");
|
||||
if (ca == null)
|
||||
throw new RuntimeException("This should NEVER be null due to bool being true");
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(ca, serverWorld), new LodBuilderConfig(generationMode), false);
|
||||
|
||||
// long duration = System.nanoTime()-t;
|
||||
|
||||
// Debug print the duration
|
||||
// System.out.println("LodChunkGenFull["+chunkX+","+chunkZ+"]: "+(double)(duration)/1000.);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* TODO: Update this chart
|
||||
* performance/generation tests related to
|
||||
* serverWorld.getChunk(x, z, ChunkStatus. *** )
|
||||
|
||||
true/false is whether they generated blocks or not
|
||||
the time is how long it took to generate
|
||||
|
||||
ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
|
||||
ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates some chunks)
|
||||
ChunkStatus.BIOMES 1 - 10 ms false (no height)
|
||||
ChunkStatus.NOISE 4 - 15 ms true (all blocks are stone)
|
||||
ChunkStatus.LIQUID_CARVERS 6 - 12 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.SURFACE 5 - 15 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.FEATURES 7 - 25 ms true
|
||||
ChunkStatus.HEIGHTMAPS 20 - 40 ms true
|
||||
ChunkStatus.LIGHT 20 - 40 ms true
|
||||
ChunkStatus.FULL 30 - 50 ms true
|
||||
ChunkStatus.SPAWN 50 - 80 ms true
|
||||
|
||||
At this point I would suggest using FEATURES, as it generates snow and trees
|
||||
(and any other object that are needed to make biomes distinct)
|
||||
|
||||
Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
|
||||
|
||||
true/false is whether they generated blocks or not
|
||||
the time is how long it took to generate
|
||||
|
||||
ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
|
||||
ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates some chunks)
|
||||
ChunkStatus.BIOMES 1 - 10 ms false (no height)
|
||||
ChunkStatus.NOISE 4 - 15 ms true (all blocks are stone)
|
||||
ChunkStatus.LIQUID_CARVERS 6 - 12 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.SURFACE 5 - 15 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.FEATURES 7 - 25 ms true
|
||||
ChunkStatus.HEIGHTMAPS 20 - 40 ms true
|
||||
ChunkStatus.LIGHT 20 - 40 ms true
|
||||
ChunkStatus.FULL 30 - 50 ms true
|
||||
ChunkStatus.SPAWN 50 - 80 ms true
|
||||
|
||||
At this point I would suggest using FEATURES, as it generates snow and trees
|
||||
(and any other object that are needed to make biomes distinct)
|
||||
|
||||
Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
|
||||
*/
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import com.seibel.lod.core.api.ModAccessorApi;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
||||
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LightChunkGetter;
|
||||
|
||||
public class LightGetterAdaptor implements LightChunkGetter {
|
||||
private final BlockGetter heightGetter;
|
||||
public LightedWorldGenRegion genRegion = null;
|
||||
final boolean shouldReturnNull;
|
||||
|
||||
public LightGetterAdaptor(BlockGetter heightAccessor) {
|
||||
this.heightGetter = heightAccessor;
|
||||
shouldReturnNull = ModAccessorApi.get(IStarlightAccessor.class) != null;
|
||||
}
|
||||
|
||||
public void setRegion(LightedWorldGenRegion region) {
|
||||
genRegion = region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockGetter getChunkForLighting(int chunkX, int chunkZ) {
|
||||
if (genRegion == null)
|
||||
throw new IllegalStateException("World Gen region has not been set!");
|
||||
// May be null
|
||||
return genRegion.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockGetter getLevel() {
|
||||
return shouldReturnNull ? null : (genRegion != null ? genRegion : heightGetter);
|
||||
}
|
||||
public LevelHeightAccessor getLevelHeightAccessor() {
|
||||
return heightGetter;
|
||||
}
|
||||
}
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ImposterProtoChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
|
||||
public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
public final WorldGenLevelLightEngine light;
|
||||
public final LightGenerationMode lightMode;
|
||||
public final EmptyChunkGenerator generator;
|
||||
public final int writeRadius;
|
||||
public final int size;
|
||||
private final ChunkPos firstPos;
|
||||
private final List<ChunkAccess> cache;
|
||||
private final StructureFeatureManager structFeat;
|
||||
Long2ObjectOpenHashMap<ChunkAccess> chunkMap = new Long2ObjectOpenHashMap<ChunkAccess>();
|
||||
|
||||
public LightedWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
|
||||
StructureFeatureManager structFeat, List<ChunkAccess> list, ChunkStatus chunkStatus, int i,
|
||||
LightGenerationMode lightMode, EmptyChunkGenerator generator) {
|
||||
super(serverLevel, list, chunkStatus, i);
|
||||
this.lightMode = lightMode;
|
||||
this.firstPos = list.get(0).getPos();
|
||||
this.generator = generator;
|
||||
this.structFeat = structFeat;
|
||||
light = lightEngine;
|
||||
writeRadius = i;
|
||||
cache = list;
|
||||
size = Mth.floor(Math.sqrt(list.size()));
|
||||
}
|
||||
|
||||
// Bypass BCLib mixin overrides.
|
||||
@Override
|
||||
public boolean ensureCanWrite(BlockPos blockPos) {
|
||||
int i = SectionPos.blockToSectionCoord(blockPos.getX());
|
||||
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
|
||||
ChunkPos chunkPos = this.getCenter();
|
||||
ChunkAccess center = this.getChunk(chunkPos.x, chunkPos.z);
|
||||
int k = Math.abs(chunkPos.x - i);
|
||||
int l = Math.abs(chunkPos.z - j);
|
||||
if (k > this.writeRadius || l > this.writeRadius) {
|
||||
return false;
|
||||
}
|
||||
if (center.isUpgrading()) {
|
||||
LevelHeightAccessor levelHeightAccessor = center.getHeightAccessorForGeneration();
|
||||
if (blockPos.getY() < levelHeightAccessor.getMinBuildHeight() || blockPos.getY() >= levelHeightAccessor.getMaxBuildHeight()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
|
||||
StructureFeature<?> structureFeature) {
|
||||
return structFeat.startsForFeature(sectionPos, structureFeature);
|
||||
}
|
||||
|
||||
// Skip updating the related tile entities
|
||||
@Override
|
||||
public boolean setBlock(BlockPos blockPos, BlockState blockState, int i, int j) {
|
||||
ChunkAccess chunkAccess = this.getChunk(blockPos);
|
||||
if (chunkAccess instanceof LevelChunk)
|
||||
return true;
|
||||
chunkAccess.setBlockState(blockPos, blockState, false);
|
||||
// This is for post ticking for water on gen and stuff like that. Not enabled
|
||||
// for now.
|
||||
// if (blockState.hasPostProcess(this, blockPos))
|
||||
// this.getChunk(blockPos).markPosForPostprocessing(blockPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip Dropping the item on destroy
|
||||
@Override
|
||||
public boolean destroyBlock(BlockPos blockPos, boolean bl, @Nullable Entity entity, int i) {
|
||||
BlockState blockState = this.getBlockState(blockPos);
|
||||
if (blockState.isAir()) {
|
||||
return false;
|
||||
}
|
||||
return this.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3, i);
|
||||
}
|
||||
|
||||
// Skip BlockEntity stuff. It aren't really needed
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(BlockPos blockPos) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip BlockEntity stuff. It aren't really needed
|
||||
@Override
|
||||
public boolean addFreshEntity(Entity entity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allays have empty chunks even if it's outside the worldGenRegion
|
||||
// @Override
|
||||
// public boolean hasChunk(int i, int j) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// Override to ensure no other mod mixins cause skipping the overrided
|
||||
// getChunk(...)
|
||||
@Override
|
||||
public ChunkAccess getChunk(int i, int j) {
|
||||
return this.getChunk(i, j, ChunkStatus.EMPTY);
|
||||
}
|
||||
|
||||
// Override to ensure no other mod mixins cause skipping the overrided
|
||||
// getChunk(...)
|
||||
@Override
|
||||
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus) {
|
||||
return this.getChunk(i, j, chunkStatus, true);
|
||||
}
|
||||
|
||||
// Use this instead of super.getChunk() to bypass C2ME concurrency checks
|
||||
private ChunkAccess superGetChunk(int x, int z, ChunkStatus cs) {
|
||||
int k = x - firstPos.x;
|
||||
int l = z - firstPos.z;
|
||||
return cache.get(k + l * size);
|
||||
}
|
||||
|
||||
// Use this instead of super.hasChunk() to bypass C2ME concurrency checks
|
||||
private boolean superHasChunk(int x, int z) {
|
||||
int k = x - firstPos.x;
|
||||
int l = z - firstPos.z;
|
||||
return l >= 0 && l < size && k >= 0 && k < size;
|
||||
}
|
||||
|
||||
// Allow creating empty chunks even if it's outside the worldGenRegion
|
||||
@Override
|
||||
@Nullable
|
||||
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus, boolean bl) {
|
||||
ChunkAccess chunk = getChunkAccess(i, j, chunkStatus, bl);
|
||||
if (chunk instanceof LevelChunk) {
|
||||
chunk = new ImposterProtoChunk((LevelChunk) chunk, true);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
private static ChunkStatus debugTriggeredForStatus = null;
|
||||
|
||||
private ChunkAccess getChunkAccess(int i, int j, ChunkStatus chunkStatus, boolean bl) {
|
||||
ChunkAccess chunk = superHasChunk(i, j) ? superGetChunk(i, j, ChunkStatus.EMPTY) : null;
|
||||
if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus)) {
|
||||
return chunk;
|
||||
}
|
||||
if (!bl)
|
||||
return null;
|
||||
if (chunk == null) {
|
||||
chunk = chunkMap.get(ChunkPos.asLong(i, j));
|
||||
if (chunk == null) {
|
||||
chunk = generator.generate(i, j);
|
||||
if (chunk == null)
|
||||
throw new NullPointerException("The provided generator should not return null!");
|
||||
chunkMap.put(ChunkPos.asLong(i, j), chunk);
|
||||
}
|
||||
}
|
||||
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
|
||||
ClientApi.LOGGER.info("WorldGen requiring " + chunkStatus
|
||||
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
|
||||
debugTriggeredForStatus = chunkStatus;
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
// Override force use of my own light engine
|
||||
@Override
|
||||
public LevelLightEngine getLightEngine() {
|
||||
return light;
|
||||
}
|
||||
|
||||
// Override force use of my own light engine
|
||||
@Override
|
||||
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
|
||||
if (lightMode != LightGenerationMode.FAST) {
|
||||
return light.getLayerListener(lightLayer).getLightValue(blockPos);
|
||||
}
|
||||
if (lightLayer == LightLayer.BLOCK)
|
||||
return 0;
|
||||
BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
|
||||
return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
|
||||
}
|
||||
|
||||
// Override force use of my own light engine
|
||||
@Override
|
||||
public int getRawBrightness(BlockPos blockPos, int i) {
|
||||
if (lightMode != LightGenerationMode.FAST) {
|
||||
return light.getRawBrightness(blockPos, i);
|
||||
}
|
||||
BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
|
||||
return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
|
||||
}
|
||||
|
||||
// Override force use of my own light engine
|
||||
@Override
|
||||
public boolean canSeeSky(BlockPos blockPos) {
|
||||
return (getBrightness(LightLayer.SKY, blockPos) >= getMaxLightLevel());
|
||||
}
|
||||
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.DataLayer;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.lighting.BlockLightEngine;
|
||||
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.lighting.SkyLightEngine;
|
||||
|
||||
public class WorldGenLevelLightEngine extends LevelLightEngine {
|
||||
public static final int MAX_SOURCE_LEVEL = 15;
|
||||
public static final int LIGHT_SECTION_PADDING = 1;
|
||||
protected final LevelHeightAccessor levelHeightAccessor;
|
||||
@Nullable
|
||||
public final BlockLightEngine blockEngine;
|
||||
@Nullable
|
||||
public final SkyLightEngine skyEngine;
|
||||
|
||||
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
|
||||
super(genRegion, false, false);
|
||||
this.levelHeightAccessor = genRegion.getLevelHeightAccessor();
|
||||
this.blockEngine = new BlockLightEngine(genRegion);
|
||||
this.skyEngine = new SkyLightEngine(genRegion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkBlock(BlockPos blockPos) {
|
||||
if (this.blockEngine != null) {
|
||||
this.blockEngine.checkBlock(blockPos);
|
||||
}
|
||||
if (this.skyEngine != null) {
|
||||
this.skyEngine.checkBlock(blockPos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
|
||||
if (this.blockEngine != null) {
|
||||
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLightWork() {
|
||||
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
|
||||
return true;
|
||||
}
|
||||
return this.blockEngine != null && this.blockEngine.hasLightWork();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int runUpdates(int i, boolean bl, boolean bl2) {
|
||||
if (this.blockEngine != null && this.skyEngine != null) {
|
||||
int j = i / 2;
|
||||
int k = this.blockEngine.runUpdates(j, bl, bl2);
|
||||
int l = i - j + k;
|
||||
int m = this.skyEngine.runUpdates(l, bl, bl2);
|
||||
if (k == 0 && m > 0) {
|
||||
return this.blockEngine.runUpdates(m, bl, bl2);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
if (this.blockEngine != null) {
|
||||
return this.blockEngine.runUpdates(i, bl, bl2);
|
||||
}
|
||||
if (this.skyEngine != null) {
|
||||
return this.skyEngine.runUpdates(i, bl, bl2);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
|
||||
if (this.blockEngine != null) {
|
||||
this.blockEngine.updateSectionStatus(sectionPos, bl);
|
||||
}
|
||||
if (this.skyEngine != null) {
|
||||
this.skyEngine.updateSectionStatus(sectionPos, bl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
|
||||
if (this.blockEngine != null) {
|
||||
this.blockEngine.enableLightSources(chunkPos, bl);
|
||||
}
|
||||
if (this.skyEngine != null) {
|
||||
this.skyEngine.enableLightSources(chunkPos, bl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
|
||||
if (lightLayer == LightLayer.BLOCK) {
|
||||
if (this.blockEngine == null) {
|
||||
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
|
||||
}
|
||||
return this.blockEngine;
|
||||
}
|
||||
if (this.skyEngine == null) {
|
||||
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
|
||||
}
|
||||
return this.skyEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawBrightness(BlockPos blockPos, int i) {
|
||||
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
|
||||
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
|
||||
return Math.max(k, j);
|
||||
}
|
||||
|
||||
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
|
||||
ChunkPos chunkPos = chunkAccess.getPos();
|
||||
chunkAccess.setLightCorrect(false);
|
||||
|
||||
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
|
||||
for (int i = 0; i < chunkAccess.getSectionsCount(); ++i) {
|
||||
LevelChunkSection levelChunkSection = levelChunkSections[i];
|
||||
if (levelChunkSection.hasOnlyAir()) continue;
|
||||
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
|
||||
updateSectionStatus(SectionPos.of(chunkPos, j), false);
|
||||
}
|
||||
enableLightSources(chunkPos, true);
|
||||
if (needLightBlockUpdate) {
|
||||
chunkAccess.getLights().forEach(blockPos ->
|
||||
onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
|
||||
}
|
||||
|
||||
chunkAccess.setLightCorrect(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
|
||||
throw new UnsupportedOperationException("This should never be used!");
|
||||
}
|
||||
@Override
|
||||
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer, boolean bl) {
|
||||
if (lightLayer == LightLayer.BLOCK) {
|
||||
if (this.blockEngine != null) {
|
||||
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
|
||||
}
|
||||
} else if (this.skyEngine != null) {
|
||||
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void retainData(ChunkPos chunkPos, boolean bl) {
|
||||
if (this.blockEngine != null) {
|
||||
this.blockEngine.retainData(chunkPos, bl);
|
||||
}
|
||||
if (this.skyEngine != null) {
|
||||
this.skyEngine.retainData(chunkPos, bl);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int getLightSectionCount() {
|
||||
throw new UnsupportedOperationException("This should never be used!");
|
||||
}
|
||||
@Override
|
||||
public int getMinLightSection() {
|
||||
throw new UnsupportedOperationException("This should never be used!");
|
||||
}
|
||||
@Override
|
||||
public int getMaxLightSection() {
|
||||
throw new UnsupportedOperationException("This should never be used!");
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
|
||||
public class WorldGenStructFeatManager extends StructureFeatureManager {
|
||||
WorldGenLevel genLevel;
|
||||
WorldGenSettings worldGenSettings;
|
||||
StructureCheck structureCheck;
|
||||
public WorldGenStructFeatManager(LevelAccessor levelAccessor, WorldGenSettings worldGenSettings,
|
||||
WorldGenLevel genLevel, StructureCheck structureCheck) {
|
||||
super(levelAccessor, worldGenSettings, structureCheck);
|
||||
this.genLevel = genLevel;
|
||||
this.worldGenSettings = worldGenSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
|
||||
if (worldGenRegion == genLevel)
|
||||
return this;
|
||||
return new WorldGenStructFeatManager(worldGenRegion, worldGenSettings, worldGenRegion, structureCheck);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnyStructureAt(BlockPos blockPos) {
|
||||
SectionPos sectionPos = SectionPos.of(blockPos);
|
||||
ChunkAccess chunk = genLevel.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES,
|
||||
false);
|
||||
if (chunk == null) return false;
|
||||
return chunk.hasAnyStructureReferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
|
||||
StructureFeature<?> structureFeature) {
|
||||
if (genLevel == null)
|
||||
return List.of();
|
||||
ChunkAccess chunk = genLevel.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES,
|
||||
false);
|
||||
if (chunk == null)
|
||||
return List.of();
|
||||
LongSet longSet = chunk.getReferencesForFeature(structureFeature);
|
||||
ImmutableList.Builder builder = ImmutableList.builder();
|
||||
LongIterator longIterator = longSet.iterator();
|
||||
while (longIterator.hasNext()) {
|
||||
long l = (Long)longIterator.next();
|
||||
SectionPos sectPos = SectionPos.of(new ChunkPos(l), genLevel.getMinSection());
|
||||
ChunkAccess startChunk = genLevel.getChunk(sectPos.x(), sectPos.z(), ChunkStatus.STRUCTURE_STARTS, false);
|
||||
if (startChunk == null) continue;
|
||||
StructureStart<?> structureStart = this.getStartForFeature(sectPos, structureFeature, startChunk);
|
||||
if (structureStart == null || !structureStart.isValid()) continue;
|
||||
builder.add(structureStart);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
|
||||
public final class StepBiomes {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
*/
|
||||
public StepBiomes(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
||||
|
||||
private ChunkAccess createBiomes(ChunkGenerator generator, Registry<Biome> registry, Blender blender, StructureFeatureManager structureFeatureManager, ChunkAccess chunkAccess) {
|
||||
if (generator instanceof NoiseBasedChunkGenerator) {
|
||||
((NoiseBasedChunkGenerator) generator).doCreateBiomes(registry, blender, structureFeatureManager, chunkAccess);
|
||||
return chunkAccess;
|
||||
} else {
|
||||
chunkAccess.fillBiomesFromNoise(generator.getBiomeSource()::getNoiseBiome, generator.climateSampler());
|
||||
return chunkAccess;
|
||||
}
|
||||
}
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkAccess> chunks) {
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepBiomes: "+chunk.getPos());
|
||||
chunk = createBiomes(environment.params.generator, environment.params.biomes, Blender.of(worldGenRegion),
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.GridList;
|
||||
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
|
||||
public final class StepFeatures {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
*/
|
||||
public StepFeatures(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.FEATURES;
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
GridList<ChunkAccess> chunks) {
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
try {
|
||||
environment.params.generator.applyBiomeDecoration(worldGenRegion, chunk,
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion));
|
||||
Blender.generateBorderTicks(worldGenRegion, chunk);
|
||||
} catch (ReportedException e) {
|
||||
e.printStackTrace();
|
||||
// FIXME: Features concurrent modification issue. Something about cocobeans just
|
||||
// aren't happy
|
||||
// For now just retry.
|
||||
}
|
||||
}/*
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
Heightmap.primeHeightmaps(chunk,
|
||||
EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,
|
||||
Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.GridList;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
|
||||
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.lighting.LightEventListener;
|
||||
|
||||
public final class StepLight {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
*/
|
||||
public StepLight(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.LIGHT;
|
||||
|
||||
public void generateGroup(LightEventListener lightEngine,
|
||||
GridList<ChunkAccess> chunks) {
|
||||
//ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
}
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
boolean hasCorrectBlockLight = (chunk instanceof LevelChunk && chunk.isLightCorrect());
|
||||
try {
|
||||
if (lightEngine == null) {
|
||||
// Do nothing
|
||||
} else if (lightEngine instanceof WorldGenLevelLightEngine) {
|
||||
((WorldGenLevelLightEngine)lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
|
||||
} else if (lightEngine instanceof ThreadedLevelLightEngine) {
|
||||
((ThreadedLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight).join();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
chunk.setLightCorrect(true);
|
||||
}
|
||||
lightEngine.runUpdates(Integer.MAX_VALUE, true, true);
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.NoiseSettings;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
|
||||
public final class StepNoise {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
*/
|
||||
public StepNoise(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
}
|
||||
|
||||
private static <T> T joinSync(CompletableFuture<T> f) {
|
||||
if (!f.isDone()) throw new RuntimeException("The future is concurrent!");
|
||||
return f.join();
|
||||
}
|
||||
public final ChunkStatus STATUS = ChunkStatus.NOISE;
|
||||
|
||||
private ChunkAccess NoiseBased$fillFromNoise(NoiseBasedChunkGenerator generator, Blender blender, StructureFeatureManager structureFeatureManager, ChunkAccess chunkAccess) {
|
||||
NoiseSettings noiseSettings = generator.settings.get().noiseSettings();
|
||||
LevelHeightAccessor levelHeightAccessor = chunkAccess.getHeightAccessorForGeneration();
|
||||
int i = Math.max(noiseSettings.minY(), levelHeightAccessor.getMinBuildHeight());
|
||||
int j = Math.min(noiseSettings.minY() + noiseSettings.height(), levelHeightAccessor.getMaxBuildHeight());
|
||||
int k = Mth.intFloorDiv(i, noiseSettings.getCellHeight());
|
||||
int l = Mth.intFloorDiv(j - i, noiseSettings.getCellHeight());
|
||||
if (l <= 0) {
|
||||
return chunkAccess;
|
||||
}
|
||||
int m = chunkAccess.getSectionIndex(l * noiseSettings.getCellHeight() - 1 + i);
|
||||
int n = chunkAccess.getSectionIndex(i);
|
||||
HashSet<LevelChunkSection> set = Sets.newHashSet();
|
||||
for (int o = m; o >= n; --o) {
|
||||
LevelChunkSection levelChunkSection = chunkAccess.getSection(o);
|
||||
levelChunkSection.acquire();
|
||||
set.add(levelChunkSection);
|
||||
}
|
||||
chunkAccess = generator.doFill(blender, structureFeatureManager, chunkAccess, k, l);
|
||||
for (LevelChunkSection levelChunkSection : set) {
|
||||
levelChunkSection.release();
|
||||
};
|
||||
return chunkAccess;
|
||||
}
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkAccess> chunks) {
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepNoise: "+chunk.getPos());
|
||||
if (environment.params.generator instanceof NoiseBasedChunkGenerator) {
|
||||
chunk = NoiseBased$fillFromNoise((NoiseBasedChunkGenerator)environment.params.generator,Blender.of(worldGenRegion),
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
|
||||
} else {
|
||||
chunk = joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.CrashReportCategory;
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
|
||||
public final class StepStructureReference {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
*/
|
||||
public StepStructureReference(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
|
||||
|
||||
private void createReferences(WorldGenRegion worldGenLevel, StructureFeatureManager structureFeatureManager,
|
||||
ChunkAccess chunkAccess) {
|
||||
ChunkPos chunkPos = chunkAccess.getPos();
|
||||
int j = chunkPos.x;
|
||||
int k = chunkPos.z;
|
||||
int l = chunkPos.getMinBlockX();
|
||||
int m = chunkPos.getMinBlockZ();
|
||||
|
||||
SectionPos sectionPos = SectionPos.bottomOf(chunkAccess);
|
||||
|
||||
for (int n = j - 8; n <= j + 8; n++) {
|
||||
for (int o = k - 8; o <= k + 8; o++) {
|
||||
if (!worldGenLevel.hasChunk(n, o))
|
||||
continue;
|
||||
long p = ChunkPos.asLong(n, o);
|
||||
for (StructureStart<?> structureStart : worldGenLevel.getChunk(n, o).getAllStarts().values()) {
|
||||
try {
|
||||
if (structureStart.isValid()
|
||||
&& structureStart.getBoundingBox().intersects(l, m, l + 15, m + 15)) {
|
||||
structureFeatureManager.addReferenceForFeature(sectionPos, structureStart.getFeature(),
|
||||
p, chunkAccess);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
CrashReport crashReport = CrashReport.forThrowable(exception,
|
||||
"Generating structure reference");
|
||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Structure");
|
||||
crashReportCategory.setDetail("Id",
|
||||
() -> Registry.STRUCTURE_FEATURE.getKey(structureStart.getFeature()).toString());
|
||||
crashReportCategory.setDetail("Name", () -> structureStart.getFeature().getFeatureName());
|
||||
crashReportCategory.setDetail("Class",
|
||||
() -> structureStart.getFeature().getClass().getCanonicalName());
|
||||
throw new ReportedException(crashReport);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkAccess> chunks) {
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepStructureReference: "+chunk.getPos());
|
||||
createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
|
||||
public final class StepStructureStart {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
*/
|
||||
public StepStructureStart(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
|
||||
|
||||
public static class StructStartCorruptedException extends RuntimeException {
|
||||
private static final long serialVersionUID = -8987434342051563358L;
|
||||
|
||||
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
|
||||
super("StructStartCorruptedException");
|
||||
super.initCause(e);
|
||||
fillInStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkAccess> chunks) {
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
if (environment.params.worldGenSettings.generateFeatures()) {
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepStructureStart: "+chunk.getPos());
|
||||
environment.params.generator.createStructures(environment.params.registry, tParams.structFeat, chunk, environment.params.structures,
|
||||
environment.params.worldSeed);
|
||||
try {
|
||||
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
// There's a rare issue with StructStart where it throws ArrayIndexOutOfBounds
|
||||
// This means the structFeat is corrupted (For some reason) and I need to reset it.
|
||||
// TODO: Figure out in the future why this happens even though I am using new structFeat
|
||||
throw new StepStructureStart.StructStartCorruptedException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
|
||||
public final class StepSurface {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
*/
|
||||
public StepSurface(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.SURFACE;
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkAccess> chunks) {
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepSurface: "+chunk.getPos());
|
||||
environment.params.generator.buildSurface(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
||||
chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
Submodule core updated: ca81ed1efe...068622895f
Reference in New Issue
Block a user