- more refactors

- tweak how biome container is generated
- block carvers from acting on chunks containing surface structures
- added spawn type option
This commit is contained in:
dags- 2020-06-05 17:12:18 +01:00
parent 011a0bf4ba
commit 94780baf98
30 changed files with 264 additions and 256 deletions

2
Engine

@ -1 +1 @@
Subproject commit 5c77c566a5e5fd035d3421c1a3b58d7d3fc7bb9d
Subproject commit a109829d3734ddf3787c48854507f388d403471f

@ -1 +1 @@
Subproject commit 8810eb585979a995ae37351cb9339ff805053a99
Subproject commit 5e99228c7d6eabffaf4f186b83069490f67e4512

View File

@ -1,5 +1,7 @@
{
"biome.terraforged.brice": "Brice",
"biome.terraforged.cold_steppe": "Cold Steppe",
"biome.terraforged.dunes": "Dunes",
"biome.terraforged.fir_forest": "Fir Forest",
"biome.terraforged.flower_plains": "Flower Plains",
"biome.terraforged.frozen_lake": "Frozen Lake",
@ -54,6 +56,9 @@
"display.terraforged.filters": "Filters",
"display.terraforged.filters.erosion": "Erosion",
"display.terraforged.filters.erosion.deposite_rate": "Deposite Rate",
"display.terraforged.filters.erosion.droplet_lifetime": "Droplet Lifetime",
"display.terraforged.filters.erosion.droplet_velocity": "Droplet Velocity",
"display.terraforged.filters.erosion.droplet_volume": "Droplet Volume",
"display.terraforged.filters.erosion.erosion_rate": "Erosion Rate",
"display.terraforged.filters.erosion.iterations": "Iterations",
"display.terraforged.filters.smoothing": "Smoothing",
@ -61,7 +66,7 @@
"display.terraforged.filters.smoothing.smoothing_radius": "Smoothing Radius",
"display.terraforged.filters.smoothing.smoothing_rate": "Smoothing Rate",
"display.terraforged.preview": "Preview",
"display.terraforged.preview.mode": "Mode",
"display.terraforged.preview.display": "Display",
"display.terraforged.preview.zoom": "Zoom",
"display.terraforged.rivers": "Rivers",
"display.terraforged.rivers.primary_rivers": "Primary Rivers",
@ -160,13 +165,14 @@
"display.terraforged.terrain.volcano.weight": "Weight",
"display.terraforged.world": "World",
"display.terraforged.world.continent": "Continent",
"display.terraforged.world.continent.continent_mode": "Continent Mode",
"display.terraforged.world.continent.continent_scale": "Continent Scale",
"display.terraforged.world.continent.continent_shape": "Continent Shape",
"display.terraforged.world.continent.ocean_scale": "Ocean Scale",
"display.terraforged.world.levels": "Levels",
"display.terraforged.world.levels.sea_level": "Sea Level",
"display.terraforged.world.levels.world_height": "World Height",
"display.terraforged.world.world_type": "World Type",
"display.terraforged.world.properties": "Properties",
"display.terraforged.world.properties.sea_level": "Sea Level",
"display.terraforged.world.properties.spawn_type": "Spawn Type",
"display.terraforged.world.properties.world_height": "World Height",
"generator.terraforged": "TerraForged",
"generator.terratest": "TerraTest",
"tooltip.terraforged.climate.biome_edge_shape.gain": "Controls the gain subsequent noise octaves",
@ -200,13 +206,14 @@
"tooltip.terraforged.features.strata_decorator": "Generates strata (rock layers) instead of just stone",
"tooltip.terraforged.features.vanilla_water_features": "Controls whether vanilla lakes & springs should generate",
"tooltip.terraforged.filters.erosion.deposite_rate": "Controls how quickly material is deposited (during erosion)",
"tooltip.terraforged.filters.erosion.droplet_lifetime": "Controls the number of iterations that a single water droplet is simulated for",
"tooltip.terraforged.filters.erosion.droplet_velocity": "Controls the starting velocity of the simulated water droplet",
"tooltip.terraforged.filters.erosion.droplet_volume": "Controls the starting volume of water that a simulated water droplet carries",
"tooltip.terraforged.filters.erosion.erosion_rate": "Controls how quickly material dissolves (during erosion)",
"tooltip.terraforged.filters.erosion.iterations": "Controls the number of erosion iterations",
"tooltip.terraforged.filters.smoothing.iterations": "Controls the number of smoothing iterations",
"tooltip.terraforged.filters.smoothing.smoothing_radius": "Controls the smoothing radius",
"tooltip.terraforged.filters.smoothing.smoothing_rate": "Controls how strongly smoothing is applied",
"tooltip.terraforged.preview.mode": "Controls the rendering mode on the preview map",
"tooltip.terraforged.preview.zoom": "Controls the zoom level of the preview map",
"tooltip.terraforged.rivers.primary_rivers.bank_width": "Controls the river-banks width",
"tooltip.terraforged.rivers.primary_rivers.bed_depth": "Controls the depth of the river",
"tooltip.terraforged.rivers.primary_rivers.bed_width": "Controls the river-bed width",
@ -279,10 +286,11 @@
"tooltip.terraforged.terrain.volcano.horizontal_scale": "Stretches or compresses the terrain horizontally",
"tooltip.terraforged.terrain.volcano.vertical_scale": "Stretches or compresses the terrain vertically",
"tooltip.terraforged.terrain.volcano.weight": "Controls how common this terrain type is",
"tooltip.terraforged.world.continent.continent_mode": "Controls the continent generator type",
"tooltip.terraforged.world.continent.continent_scale": "Controls the size of continents",
"tooltip.terraforged.world.continent.continent_shape": "Controls how continent shapes calculated",
"tooltip.terraforged.world.continent.continent_shape": "Controls how continent shapes are calculated",
"tooltip.terraforged.world.continent.ocean_scale": "Controls the amount of ocean between continents",
"tooltip.terraforged.world.levels.sea_level": "Controls the sea level",
"tooltip.terraforged.world.levels.world_height": "Controls the world height",
"tooltip.terraforged.world.world_type": "Controls the continent generator type"
"tooltip.terraforged.world.properties.sea_level": "Controls the sea level",
"tooltip.terraforged.world.properties.spawn_type": "Set whether spawn should be close to x=0,z=0 or the centre of the nearest continent",
"tooltip.terraforged.world.properties.world_height": "Controls the world height"
}

View File

@ -38,11 +38,11 @@ public class Delegate implements Surface {
private final ConfiguredSurfaceBuilder<?> surfaceBuilder;
private Delegate(Biome biome) {
public Delegate(Biome biome) {
this(biome.getSurfaceBuilder());
}
private Delegate(ConfiguredSurfaceBuilder<?> surfaceBuilder) {
public Delegate(ConfiguredSurfaceBuilder<?> surfaceBuilder) {
this.surfaceBuilder = surfaceBuilder;
}

View File

@ -33,7 +33,6 @@ import com.terraforged.chunk.TerraContext;
import com.terraforged.core.cell.Cell;
import com.terraforged.world.biome.BiomeType;
import com.terraforged.world.terrain.ITerrain;
import com.terraforged.world.terrain.TerrainType;
import net.minecraft.world.biome.Biome;
import java.util.ArrayList;

View File

@ -40,7 +40,7 @@ public class SandBiomeModifier extends AbstractMaxHeightModifier {
private final Set<Biome> biomes;
public SandBiomeModifier(TerraContext context) {
super(context.seed, context.factory.getClimate(), 50, 2, context.levels.scale(16), context.levels.ground(10), context.levels.ground(25));
super(context.seed, context.factory.getClimate(), 10, 1, context.levels.scale(8), context.levels.ground(10), context.levels.ground(25));
this.biomes = ForgeRegistries.BIOMES.getValues().stream()
.filter(biome -> context.materials.isSand(biome.getSurfaceBuilderConfig().getTop().getBlock()))
.collect(Collectors.toSet());

View File

@ -3,7 +3,6 @@ package com.terraforged.biome.provider;
import com.terraforged.core.cell.Cell;
import com.terraforged.world.heightmap.Levels;
import com.terraforged.world.terrain.TerrainType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;
public class BiomeAccess {

View File

@ -28,20 +28,14 @@ package com.terraforged.biome.provider;
import com.google.common.collect.Sets;
import com.terraforged.biome.map.BiomeMap;
import com.terraforged.biome.modifier.BiomeModifierManager;
import com.terraforged.chunk.TerraChunkGenerator;
import com.terraforged.chunk.TerraContext;
import com.terraforged.chunk.util.FastChunk;
import com.terraforged.chunk.util.TerraContainer;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.concurrent.Resource;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.util.setup.SetupHooks;
import com.terraforged.world.heightmap.WorldLookup;
import com.terraforged.world.terrain.decorator.Decorator;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunk;
import java.util.Collections;
import java.util.HashMap;
@ -148,15 +142,6 @@ public class BiomeProvider extends AbstractBiomeProvider {
return decorators.getOrDefault(biome, Collections.emptyList());
}
public TerraContainer createBiomeContainer(ChunkReader chunkReader) {
TerraContainer.Builder builder = TerraContainer.builder();
chunkReader.iterate((cell, dx, dz) -> {
Biome biome = getBiome(cell, chunkReader.getBlockX() + dx, chunkReader.getBlockZ() + dz);
builder.set(dx, dz, biome);
});
return builder.build(chunkReader);
}
public Biome getBiome(Cell cell, int x, int z) {
BiomeAccessor accessor = biomeAccess.getAccessor(cell);
Biome biome = accessor.getBiome(biomeMap, cell);
@ -169,20 +154,4 @@ public class BiomeProvider extends AbstractBiomeProvider {
public boolean canSpawnAt(Cell cell) {
return cell.terrain != context.terrain.ocean && cell.terrain != context.terrain.deepOcean;
}
public static TerraContainer getBiomeContainer(TerraChunkGenerator generator, IChunk chunk) {
if (chunk.getBiomes() instanceof TerraContainer) {
return (TerraContainer) chunk.getBiomes();
}
ChunkReader view = generator.getChunkReader(chunk.getPos().x, chunk.getPos().z);
TerraContainer container = generator.getBiomeProvider().createBiomeContainer(view);
if (chunk instanceof ChunkPrimer) {
((ChunkPrimer) chunk).func_225548_a_(container);
} else if (chunk instanceof FastChunk) {
((FastChunk) chunk).setBiomes(container);
}
return container;
}
}

View File

@ -3,7 +3,10 @@ package com.terraforged.biome.spawn;
import com.terraforged.Log;
import com.terraforged.biome.provider.BiomeProvider;
import com.terraforged.world.continent.MutableVeci;
import com.terraforged.world.continent.SpawnType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.IFeatureConfig;
@ -19,12 +22,17 @@ public class SpawnHandler {
public static void createSpawn(WorldEvent.CreateSpawnPosition event) {
if (event.getWorld() instanceof ServerWorld) {
ServerWorld world =(ServerWorld) event.getWorld();
if (world.getChunkProvider().getChunkGenerator().getBiomeProvider() instanceof BiomeProvider) {
ChunkGenerator<?> generator = world.getChunkProvider().getChunkGenerator();
if (generator.getBiomeProvider() instanceof BiomeProvider) {
Log.info("Searching for world spawn position");
BiomeProvider provider = (BiomeProvider) world.getChunkProvider().getChunkGenerator().getBiomeProvider();
BlockPos center = getSearchCenter(provider, true);
BiomeProvider provider = (BiomeProvider) generator.getBiomeProvider();
BlockPos center = getSearchCenter(provider);
SpawnSearch search = new SpawnSearch(center, provider);
BlockPos spawn = search.get();
// SpawnSearch uses a rough look-up that does not account for the effects of erosion which
// can add or remove from the heightmap depending on location. Use the chunk generator's
// surface lookup function to obtain the actual height
BlockPos spawn = getSurface(generator, search.get());
Log.info("Setting world spawn: {}", spawn);
event.setCanceled(true);
@ -38,13 +46,20 @@ public class SpawnHandler {
}
}
private static BlockPos getSearchCenter(BiomeProvider provider, boolean continent) {
if (continent) {
private static BlockPos getSearchCenter(BiomeProvider provider) {
SpawnType spawnType = provider.getContext().terraSettings.world.properties.spawnType;
if (spawnType == SpawnType.WORLD_ORIGIN) {
return BlockPos.ZERO;
} else {
MutableVeci pos = new MutableVeci();
provider.getContext().heightmap.getContinent().getNearestCenter(0, 0, pos);
return new BlockPos(pos.x, 0, pos.z);
}
return BlockPos.ZERO;
}
private static BlockPos getSurface(ChunkGenerator<?> generator, BlockPos pos) {
int surface = generator.func_222529_a(pos.getX(), pos.getZ(), Heightmap.Type.WORLD_SURFACE_WG);
return new BlockPos(pos.getX(), surface, pos.getZ());
}
private static void createBonusChest(ServerWorld world, BlockPos pos) {

View File

@ -29,8 +29,15 @@ import com.terraforged.api.chunk.column.ColumnDecorator;
import com.terraforged.api.chunk.surface.SurfaceManager;
import com.terraforged.api.material.layer.LayerManager;
import com.terraforged.biome.provider.BiomeProvider;
import com.terraforged.chunk.generator.*;
import com.terraforged.chunk.generator.BiomeGenerator;
import com.terraforged.chunk.generator.FeatureGenerator;
import com.terraforged.chunk.generator.MobGenerator;
import com.terraforged.chunk.generator.StructureGenerator;
import com.terraforged.chunk.generator.SurfaceGenerator;
import com.terraforged.chunk.generator.TerrainCarver;
import com.terraforged.chunk.generator.TerrainGenerator;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.region.Region;
import com.terraforged.core.region.Size;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.core.region.gen.RegionCache;
@ -47,7 +54,11 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeManager;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.*;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.GenerationSettings;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.WorldGenRegion;
import net.minecraft.world.gen.feature.template.TemplateManager;
import net.minecraft.world.server.ServerWorld;
@ -63,6 +74,7 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
private final TerrainCarver terrainCarver;
private final TerrainGenerator terrainGenerator;
private final SurfaceGenerator surfaceGenerator;
private final FeatureGenerator featureGenerator;
private final StructureGenerator structureGenerator;
private final GeoManager geologyManager;
@ -84,6 +96,7 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
this.terrainCarver = new TerrainCarver(this);
this.terrainGenerator = new TerrainGenerator(this);
this.surfaceGenerator = new SurfaceGenerator(this);
this.featureGenerator = new FeatureGenerator(this);
this.structureGenerator = new StructureGenerator(this);
this.surfaceManager = TerraSetupFactory.createSurfaceManager(context);
@ -131,7 +144,7 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
@Override
public final void decorate(WorldGenRegion region) {
terrainGenerator.generateFeatures(region);
featureGenerator.generateFeatures(region);
}
@Override
@ -238,6 +251,12 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
regionCache.queueRegion(rx, rz);
}
public final Region getRegion(int chunkX, int chunkZ) {
int rx = regionCache.chunkToRegion(chunkX);
int rz = regionCache.chunkToRegion(chunkZ);
return regionCache.getRegion(rx, rz);
}
public final ChunkReader getChunkReader(int chunkX, int chunkZ) {
return regionCache.getChunk(chunkX, chunkZ);
}

View File

@ -2,11 +2,9 @@ package com.terraforged.chunk.generator;
import com.terraforged.chunk.TerraChunkGenerator;
import com.terraforged.chunk.util.TerraContainer;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.world.terrain.decorator.Decorator;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunk;
public class BiomeGenerator {
@ -19,15 +17,13 @@ public class BiomeGenerator {
public void generateBiomes(IChunk chunk) {
ChunkPos pos = chunk.getPos();
ChunkReader reader = generator.getChunkReader(pos.x, pos.z);
TerraContainer container = generator.getBiomeProvider().createBiomeContainer(reader);
((ChunkPrimer) chunk).func_225548_a_(container);
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
// apply chunk-local heightmap modifications
preProcess(pos, reader, container);
preProcess(pos, container);
}
private void preProcess(ChunkPos pos, ChunkReader chunk, TerraContainer container) {
chunk.iterate((cell, dx, dz) -> {
private void preProcess(ChunkPos pos, TerraContainer container) {
container.getChunkReader().iterate((cell, dx, dz) -> {
Biome biome = container.getBiome(dx, dz);
for (Decorator decorator : generator.getBiomeProvider().getDecorators(biome)) {
if (decorator.apply(cell, pos.getXStart() + dx, pos.getZStart() + dz)) {

View File

@ -0,0 +1,64 @@
package com.terraforged.chunk.generator;
import com.terraforged.api.chunk.column.ColumnDecorator;
import com.terraforged.api.chunk.column.DecoratorContext;
import com.terraforged.chunk.TerraChunkGenerator;
import com.terraforged.chunk.fix.RegionFix;
import com.terraforged.chunk.util.TerraContainer;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.util.Environment;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.WorldGenRegion;
import java.util.List;
public class FeatureGenerator {
private final TerraChunkGenerator generator;
public FeatureGenerator(TerraChunkGenerator generator) {
this.generator = generator;
}
public final void generateFeatures(WorldGenRegion region) {
int chunkX = region.getMainChunkX();
int chunkZ = region.getMainChunkZ();
IChunk chunk = region.getChunk(chunkX, chunkZ);
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
ChunkReader chunkReader = generator.getChunkReader(chunkX, chunkZ);
Biome biome = container.getFeatureBiome(chunkReader);
DecoratorContext context = generator.getContext().decorator(chunk);
IWorld regionFix = new RegionFix(region, generator);
BlockPos pos = new BlockPos(context.blockX, 0, context.blockZ);
// place biome features
generator.getFeatureManager().decorate(generator, regionFix, chunk, biome, pos);
// run post processes on chunk
postProcess(chunkReader, container, context);
// bake biome array & discard gen data
((ChunkPrimer) chunk).func_225548_a_(container.bakeBiomes(Environment.isVanillaBiomes()));
}
private void postProcess(ChunkReader chunk, TerraContainer container, DecoratorContext context) {
List<ColumnDecorator> decorators = generator.getPostProcessors();
container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> {
int px = ctx.blockX + dx;
int pz = ctx.blockZ + dz;
int py = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz);
ctx.cell = cell;
ctx.biome = container.getBiome(dx, dz);
for (ColumnDecorator decorator : decorators) {
decorator.decorate(ctx.chunk, ctx, px, py, pz);
}
});
}
}

View File

@ -3,7 +3,6 @@ package com.terraforged.chunk.generator;
import com.terraforged.api.chunk.column.ColumnDecorator;
import com.terraforged.api.chunk.surface.ChunkSurfaceBuffer;
import com.terraforged.api.chunk.surface.SurfaceContext;
import com.terraforged.biome.provider.BiomeProvider;
import com.terraforged.chunk.TerraChunkGenerator;
import com.terraforged.chunk.util.FastChunk;
import com.terraforged.chunk.util.TerraContainer;
@ -25,7 +24,7 @@ public class SurfaceGenerator {
}
public final void generateSurface(WorldGenRegion world, IChunk chunk) {
TerraContainer container = BiomeProvider.getBiomeContainer(generator, chunk);
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
ChunkSurfaceBuffer buffer = new ChunkSurfaceBuffer(FastChunk.wrap(chunk));
try (SurfaceContext context = generator.getContext().surface(buffer, generator.getSettings())) {

View File

@ -2,6 +2,7 @@ package com.terraforged.chunk.generator;
import com.terraforged.chunk.TerraChunkGenerator;
import com.terraforged.chunk.fix.ChunkCarverFix;
import com.terraforged.fm.template.StructureUtils;
import net.minecraft.util.SharedSeedRandom;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
@ -11,7 +12,6 @@ import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.carver.ConfiguredCarver;
import java.util.BitSet;
import java.util.List;
import java.util.ListIterator;
public class TerrainCarver {
@ -23,26 +23,23 @@ public class TerrainCarver {
}
public void carveTerrain(BiomeManager biomes, IChunk chunk, GenerationStage.Carving type) {
// World carvers have hardcoded 'carvable' blocks which can be problematic with modded blocks
// AirCarverFix shims the actual blockstates to an equivalent carvable type
if (StructureUtils.hasOvergroundStructure(chunk)) {
return;
}
chunk = new ChunkCarverFix(chunk, generator.getContext().materials);
SharedSeedRandom random = new SharedSeedRandom();
ChunkPos chunkpos = chunk.getPos();
int chunkX = chunkpos.x;
int chunkZ = chunkpos.z;
BitSet mask = chunk.getCarvingMask(type);
Biome biome = generator.getBiome(biomes, chunkpos.asBlockPos());
List<ConfiguredCarver<?>> carvers = biome.getCarvers(type);
ListIterator<ConfiguredCarver<?>> iterator = carvers.listIterator();
for(int cx = chunkX - 8; cx <= chunkX + 8; ++cx) {
for(int cz = chunkZ - 8; cz <= chunkZ + 8; ++cz) {
while(iterator.hasNext()) {
for (int cx = chunkX - 8; cx <= chunkX + 8; ++cx) {
for (int cz = chunkZ - 8; cz <= chunkZ + 8; ++cz) {
ListIterator<ConfiguredCarver<?>> iterator = biome.getCarvers(type).listIterator();
while (iterator.hasNext()) {
int index = iterator.nextIndex();
ConfiguredCarver<?> carver = iterator.next();
random.setLargeFeatureSeed(generator.getSeed() + index, cx, cz);

View File

@ -1,28 +1,16 @@
package com.terraforged.chunk.generator;
import com.terraforged.api.chunk.column.ColumnDecorator;
import com.terraforged.api.chunk.column.DecoratorContext;
import com.terraforged.biome.provider.BiomeProvider;
import com.terraforged.chunk.TerraChunkGenerator;
import com.terraforged.chunk.column.ChunkPopulator;
import com.terraforged.chunk.fix.RegionFix;
import com.terraforged.chunk.util.FastChunk;
import com.terraforged.chunk.util.TerraContainer;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.feature.TerrainHelper;
import com.terraforged.util.Environment;
import com.terraforged.world.climate.Climate;
import com.terraforged.world.heightmap.Levels;
import com.terraforged.world.terrain.Terrains;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.WorldGenRegion;
import java.util.List;
public class TerrainGenerator {
@ -41,54 +29,17 @@ public class TerrainGenerator {
}
public final void generateTerrain(IWorld world, IChunk chunk) {
TerraContainer container = BiomeProvider.getBiomeContainer(generator, chunk);
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
try (DecoratorContext context = new DecoratorContext(FastChunk.wrap(chunk), levels, terrain, climate)) {
container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> {
int px = ctx.blockX + dx;
int pz = ctx.blockZ + dz;
int py = ctx.levels.scale(cell.value);
ctx.cell = cell;
ctx.biome = container.getBiome(dx, dz);
ctx.biome = container.getNoiseBiome(dx, world.getSeaLevel(), dz);
ChunkPopulator.INSTANCE.decorate(ctx.chunk, ctx, px, py, pz);
});
terrainHelper.flatten(world, chunk);
}
}
public final void generateFeatures(WorldGenRegion region) {
int chunkX = region.getMainChunkX();
int chunkZ = region.getMainChunkZ();
IChunk chunk = region.getChunk(chunkX, chunkZ);
TerraContainer container = BiomeProvider.getBiomeContainer(generator, chunk);
Biome biome = container.getFeatureBiome();
DecoratorContext context = generator.getContext().decorator(chunk);
IWorld regionFix = new RegionFix(region, generator);
BlockPos pos = new BlockPos(context.blockX, 0, context.blockZ);
// place biome features
generator.getFeatureManager().decorate(generator, regionFix, chunk, biome, pos);
// run post processes on chunk
postProcess(container.getChunkReader(), container, context);
// bake biome array & discard gen data
((ChunkPrimer) chunk).func_225548_a_(container.bakeBiomes(Environment.isVanillaBiomes()));
container.getChunkReader().dispose();
}
private void postProcess(ChunkReader chunk, TerraContainer container, DecoratorContext context) {
List<ColumnDecorator> decorators = generator.getPostProcessors();
chunk.iterate(context, (cell, dx, dz, ctx) -> {
int px = ctx.blockX + dx;
int pz = ctx.blockZ + dz;
int py = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz);
ctx.cell = cell;
ctx.biome = container.getBiome(dx, dz);
for (ColumnDecorator decorator : decorators) {
decorator.decorate(ctx.chunk, ctx, px, py, pz);
}
});
}
}

View File

@ -1,45 +1,23 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.chunk.util;
import com.terraforged.api.biome.BiomeVariant;
import com.terraforged.chunk.TerraChunkGenerator;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.core.util.PosIterator;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeContainer;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunk;
// holds a 1:1 map of biomes in the chunk
// also holds the chunk's view on the heightmap for convenience
public class TerraContainer extends BiomeContainer {
private static final int BITS_WIDTH = (int) Math.round(Math.log(16.0D) / Math.log(2.0D)) - 2;
private static final int ZOOM_VERT = (int) Math.round(Math.log(256.0D) / Math.log(2.0D)) - 2;
public static final int SIZE = 1 << BITS_WIDTH + BITS_WIDTH + ZOOM_VERT;
public static final int BIOMES_3D_SIZE = 1 << BITS_WIDTH + BITS_WIDTH + ZOOM_VERT;
public static final int BIOMES_2D_SIZE = 16 * 16;
public static final int MASK_HORIZ = (1 << BITS_WIDTH) - 1;
public static final int MASK_VERT = (1 << ZOOM_VERT) - 1;
@ -47,23 +25,24 @@ public class TerraContainer extends BiomeContainer {
private final Biome[] surface;
private final ChunkReader chunkReader;
public TerraContainer(Builder builder, ChunkReader chunkReader) {
super(builder.biomes);
public TerraContainer(Biome[] biomes, Biome[] surface, ChunkReader chunkReader) {
super(biomes);
this.biomes = biomes;
this.surface = surface;
this.chunkReader = chunkReader;
this.biomes = builder.biomes;
this.surface = builder.surfaceBiomeCache;
}
public ChunkReader getChunkReader() {
return chunkReader;
}
public Biome getBiome(int x, int z) {
return surface[indexOf(x, z)];
x &= 15;
z &= 15;
return surface[z * 16 + x];
}
@Override
public Biome getNoiseBiome(int x, int y, int z) {
return super.getNoiseBiome(x, y, z);
}
public Biome getFeatureBiome() {
public Biome getFeatureBiome(ChunkReader chunkReader) {
PosIterator iterator = PosIterator.area(0, 0, 16, 16);
while (iterator.next()) {
Cell cell = chunkReader.getCell(iterator.x(), iterator.z());
@ -89,50 +68,47 @@ public class TerraContainer extends BiomeContainer {
return new BiomeContainer(biomes);
}
public ChunkReader getChunkReader() {
return chunkReader;
public static TerraContainer getOrCreate(IChunk chunk, TerraChunkGenerator generator) {
if (chunk.getBiomes() instanceof TerraContainer) {
return (TerraContainer) chunk.getBiomes();
} else {
TerraContainer container = TerraContainer.create(generator, chunk.getPos());
((ChunkPrimer) chunk).func_225548_a_(container);
return container;
}
}
public static TerraContainer create(TerraChunkGenerator generator, ChunkPos pos) {
ChunkReader reader = generator.getChunkReader(pos.x, pos.z);
Biome[] biomes2D = new Biome[BIOMES_2D_SIZE];
Biome[] biomes3D = new Biome[BIOMES_3D_SIZE];
PosIterator iterator = PosIterator.area(0, 0, 16, 16);
while (iterator.next()) {
int dx = iterator.x();
int dz = iterator.z();
int x = pos.getXStart() + dx;
int z = pos.getZStart() + dz;
Biome biome = generator.getBiomeProvider().getBiome(reader.getCell(dx, dz), x, z);
biomes2D[indexOf(dx, dz)] = biome;
if ((dx & 3) == 0 && (dz & 3) == 0) {
for (int dy = 0; dy < 64; dy++) {
biomes3D[indexOf(dx >> 2, dy, dz >> 2)] = biome;
}
}
}
return new TerraContainer(biomes3D, biomes2D, reader);
}
private static int indexOf(int x, int z) {
x &= 15;
z &= 15;
return (z << 4) + x;
}
private static int indexOf(int x, int y, int z) {
public static int indexOf(int x, int y, int z) {
x &= MASK_HORIZ;
y = MathHelper.clamp(y, 0, MASK_VERT);
z &= MASK_HORIZ;
return y << BITS_WIDTH + BITS_WIDTH | z << BITS_WIDTH | x;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final Biome[] biomes = new Biome[SIZE];
private final Biome[] surfaceBiomeCache = new Biome[256];
public void set(int x, int z, Biome biome) {
surfaceBiomeCache[indexOf(x, z)] = biome;
}
public TerraContainer build(ChunkReader chunkReader) {
// biome storage format is 1 biome pos == 4x4x4 blocks, stored in an 4x64x4 (xyz) array
// sample the 1:1 surfaceBiomeCache every 4 blocks with a 2 block offset (roughly center of the 4x4 area)
for (int dy = 0; dy < 64; dy++) {
for (int dz = 0; dz < 4; dz++) {
for (int dx = 0; dx < 4; dx++) {
int x = dx * 4;
int z = dz * 4;
int index = indexOf(dx, dy, dz);
biomes[index] = surfaceBiomeCache[indexOf(x, z)];
}
}
}
return new TerraContainer(this, chunkReader);
}
}
}
}

View File

@ -1,7 +1,7 @@
package com.terraforged.data;
import com.terraforged.core.util.NameUtil;
import com.terraforged.gui.preview.PreviewSettings;
import com.terraforged.gui.preview2.PreviewSettings;
import com.terraforged.settings.TerraSettings;
import com.terraforged.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT;

View File

@ -39,7 +39,11 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.jigsaw.JigsawPattern;
import net.minecraft.world.gen.feature.structure.*;
import net.minecraft.world.gen.feature.structure.AbstractVillagePiece;
import net.minecraft.world.gen.feature.structure.IStructurePieceType;
import net.minecraft.world.gen.feature.structure.Structure;
import net.minecraft.world.gen.feature.structure.StructurePiece;
import net.minecraft.world.gen.feature.structure.StructureStart;
import java.util.List;
import java.util.Set;

View File

@ -3,8 +3,8 @@ package com.terraforged.feature.context;
import com.terraforged.chunk.fix.RegionDelegate;
import com.terraforged.chunk.util.TerraContainer;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.concurrent.pool.ObjectPool;
import com.terraforged.core.concurrent.Resource;
import com.terraforged.core.concurrent.pool.ObjectPool;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.world.heightmap.Levels;
import net.minecraft.util.math.BlockPos;

View File

@ -31,8 +31,7 @@ import com.terraforged.gui.page.PresetsPage;
import com.terraforged.gui.page.SimplePage;
import com.terraforged.gui.page.SimplePreviewPage;
import com.terraforged.gui.page.WorldPage;
import com.terraforged.gui.preview.PreviewPage;
import com.terraforged.gui.preview.again.PreviewPage2;
import com.terraforged.gui.preview2.PreviewPage;
import com.terraforged.settings.SettingsHelper;
import com.terraforged.settings.TerraSettings;
import com.terraforged.util.nbt.NBTHelper;
@ -49,7 +48,7 @@ public class SettingsScreen extends OverlayScreen {
private static final Button.IPressable NO_ACTION = b -> {};
private final Page[] pages;
private final PreviewPage2 preview;
private final PreviewPage preview;
private final CreateWorldScreen parent;
private final TerraSettings settings = new TerraSettings();
@ -58,7 +57,7 @@ public class SettingsScreen extends OverlayScreen {
public SettingsScreen(CreateWorldScreen parent) {
SettingsHelper.applyDefaults(parent.chunkProviderSettingsJson, settings);
this.parent = parent;
this.preview = new PreviewPage2(settings, getSeed(parent));
this.preview = new PreviewPage(settings, getSeed(parent));
this.pages = new Page[]{
new PresetsPage(),
new WorldPage(settings, preview),

View File

@ -28,7 +28,6 @@ package com.terraforged.gui.page;
import com.terraforged.TerraWorld;
import com.terraforged.gui.OverlayScreen;
import com.terraforged.gui.element.TerraTextInput;
import com.terraforged.gui.preview.PreviewPage;
import com.terraforged.settings.TerraSettings;
import com.terraforged.util.nbt.NBTHelper;
import net.minecraft.client.gui.widget.Widget;
@ -87,7 +86,10 @@ public class WorldPage extends BasePage {
protected void update() {
super.update();
preview.apply(settings -> NBTHelper.deserialize(worldSettings, settings.world));
preview.apply(settings -> {
NBTHelper.deserialize(worldSettings, settings.world);
NBTHelper.deserialize(dimSettings, settings.dimensions);
});
}
private static ListNBT getWorldTypes() {

View File

@ -56,7 +56,7 @@ public class Preview extends Button {
private static final int FACTOR = 4;
public static final int WIDTH = Size.chunkToBlock(1 << FACTOR);
private static final int SLICE_HEIGHT = 64;
public static final int HEIGHT = WIDTH + SLICE_HEIGHT;//Size.chunkToBlock(1 << FACTOR);
public static final int HEIGHT = WIDTH + SLICE_HEIGHT;
private static final float[] LEGEND_SCALES = {1, 0.9F, 0.75F, 0.6F};
private final int offsetX;
@ -159,8 +159,8 @@ public class Preview extends Button {
float zoomUnit = 1F - (zoom / 100F);
float zoomStrength = 0.5F;
float unit = (1 - zoomStrength) + (zoomStrength * zoomUnit);
float heightModifier = settings.world.levels.worldHeight / 256F;
float waterLevelModifier = settings.world.levels.seaLevel / (float) settings.world.levels.worldHeight;
float heightModifier = settings.world.properties.worldHeight / 256F;
float waterLevelModifier = settings.world.properties.seaLevel / (float) settings.world.properties.worldHeight;
float imageWaterLevelY = image.getHeight() - 1 - (waterLevelModifier * SLICE_HEIGHT * unit);
region.iterate((cell, x, z) -> {

View File

@ -27,7 +27,6 @@ package com.terraforged.gui.preview;
import com.terraforged.gui.OverlayScreen;
import com.terraforged.gui.element.TerraButton;
import com.terraforged.gui.page.BasePage;
import com.terraforged.gui.page.UpdatablePage;
import com.terraforged.settings.TerraSettings;
import com.terraforged.util.nbt.NBTHelper;

View File

@ -1,14 +0,0 @@
package com.terraforged.gui.preview.again;
import com.terraforged.core.render.RenderMode;
import com.terraforged.core.serialization.annotation.Range;
import com.terraforged.core.serialization.annotation.Serializable;
@Serializable
public class PreviewSettings {
@Range(min = 1, max = 200)
public float zoom = 10F;
public RenderMode renderMode = RenderMode.BIOME_TYPE;
}

View File

@ -1,4 +1,4 @@
package com.terraforged.gui.preview.again;
package com.terraforged.gui.preview2;
import com.mojang.blaze3d.systems.RenderSystem;
import com.terraforged.core.render.RenderAPI;

View File

@ -1,4 +1,4 @@
package com.terraforged.gui.preview.again;
package com.terraforged.gui.preview2;
import com.terraforged.core.render.RenderBuffer;
import net.minecraft.client.renderer.BufferBuilder;

View File

@ -1,4 +1,4 @@
package com.terraforged.gui.preview.again;
package com.terraforged.gui.preview2;
import com.mojang.blaze3d.systems.RenderSystem;
import com.terraforged.core.concurrent.thread.ThreadPool;
@ -10,11 +10,14 @@ import com.terraforged.core.render.RenderWorld;
import com.terraforged.settings.TerraSettings;
import com.terraforged.world.GeneratorContext;
import com.terraforged.world.continent.MutableVeci;
import com.terraforged.world.continent.SpawnType;
import com.terraforged.world.terrain.Terrains;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.renderer.RenderHelper;
public class Preview2 extends Widget {
public class Preview extends Widget {
private static final float ZOOM_SCALE = 200F;
private final ThreadPool threadPool = ThreadPools.getPool();
@ -28,7 +31,7 @@ public class Preview2 extends Widget {
private RenderWorld world;
private PreviewSettings previewSettings = new PreviewSettings();
public Preview2(TerraSettings settings, int seed) {
public Preview(TerraSettings settings, int seed) {
super(0, 0, "preview");
this.seed = seed;
this.settings = settings;
@ -79,8 +82,8 @@ public class Preview2 extends Widget {
public void update(PreviewSettings settings, TerraSettings genSettings) {
this.previewSettings = settings;
// this.world = createWorld(genSettings);
world.update(offsetX, offsetZ, previewSettings.zoom, true);
this.world = createWorld(genSettings);
world.update(offsetX, offsetZ, previewSettings.getZoom(ZOOM_SCALE), true);
}
private RenderWorld createWorld(TerraSettings settings) {
@ -90,7 +93,12 @@ public class Preview2 extends Widget {
GeneratorContext context = GeneratorContext.createNoCache(Terrains.create(settings), settings);
MutableVeci center = new MutableVeci();
context.factory.getHeightmap().getContinent().getNearestCenter(0, 0, center);
if (settings.world.properties.spawnType == SpawnType.CONTINENT_CENTER) {
context.factory.getHeightmap().getContinent().getNearestCenter(0, 0, center);
}
offsetX = center.x;
offsetZ = center.z;
RegionGenerator generator = RegionGenerator.builder()
.pool(threadPool)
@ -103,8 +111,8 @@ public class Preview2 extends Widget {
RenderSettings renderSettings = new RenderSettings(context);
renderSettings.width = width;
renderSettings.height = height;
renderSettings.zoom = previewSettings.zoom;
renderSettings.renderMode = previewSettings.renderMode;
renderSettings.zoom = previewSettings.getZoom(ZOOM_SCALE);
renderSettings.renderMode = previewSettings.display;
return new RenderWorld(generator, renderAPI, renderSettings, regions, size);
}

View File

@ -1,24 +1,23 @@
package com.terraforged.gui.preview.again;
package com.terraforged.gui.preview2;
import com.terraforged.gui.OverlayScreen;
import com.terraforged.gui.element.TerraButton;
import com.terraforged.gui.page.UpdatablePage;
import com.terraforged.gui.preview.Preview;
import com.terraforged.settings.TerraSettings;
import com.terraforged.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT;
import java.util.function.Consumer;
public class PreviewPage2 extends UpdatablePage {
public class PreviewPage extends UpdatablePage {
private final Preview2 preview;
private final Preview preview;
private final CompoundNBT settings;
private final TerraSettings genSettings = new TerraSettings();
public PreviewPage2(TerraSettings settings, int seed) {
this.preview = new Preview2(settings, seed);
this.settings = NBTHelper.serialize(new PreviewSettings());
public PreviewPage(TerraSettings settings, int seed) {
this.preview = new Preview(settings, seed);
this.settings = NBTHelper.serialize("preview", new PreviewSettings());
}
public int getSeed() {
@ -27,7 +26,7 @@ public class PreviewPage2 extends UpdatablePage {
@Override
public void apply(Consumer<TerraSettings> consumer) {
// consumer.accept(genSettings);
consumer.accept(genSettings);
update();
}
@ -36,8 +35,8 @@ public class PreviewPage2 extends UpdatablePage {
Column right = getColumn(1);
preview.x = 0;
preview.y = 0;
preview.setWidth(Preview.WIDTH);
preview.setHeight(Preview.HEIGHT);
preview.setWidth(com.terraforged.gui.preview.Preview.WIDTH);
preview.setHeight(com.terraforged.gui.preview.Preview.HEIGHT);
addElements(right.left, right.top, right, settings, right.scrollPane::addButton, this::update);
@ -57,7 +56,7 @@ public class PreviewPage2 extends UpdatablePage {
right.scrollPane.addButton(spacer);
}
update();
// update();
}
@Override

View File

@ -0,0 +1,19 @@
package com.terraforged.gui.preview2;
import com.terraforged.core.render.RenderMode;
import com.terraforged.core.serialization.annotation.Range;
import com.terraforged.core.serialization.annotation.Serializable;
@Serializable
public class PreviewSettings {
@Range(min = 1, max = 100)
public float zoom = 90F;
public RenderMode display = RenderMode.BIOME_TYPE;
public float getZoom(float scale) {
float perc = (101F - zoom) / 100F;
return perc * scale;
}
}

View File

@ -25,8 +25,8 @@
package com.terraforged.util;
import com.terraforged.core.concurrent.pool.ObjectPool;
import com.terraforged.core.concurrent.Resource;
import com.terraforged.core.concurrent.pool.ObjectPool;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.fluid.FluidState;