- improve how terrain is cut out above village pieces

- further refinements to transition points
- fix incorrect preset jsons
- improve accuracy of biome lookups
This commit is contained in:
dags- 2020-06-30 12:16:42 +01:00
parent a73058062c
commit 2edc791a3d
18 changed files with 112 additions and 47 deletions

2
Engine

@ -1 +1 @@
Subproject commit d9dee330393aa0bce3bc69920734d80617c82be2 Subproject commit b4fd74c174412ca08d72c694dad5ee85e1e95d9e

View File

@ -109,8 +109,8 @@ classes {
dependsOn(collectLibs) dependsOn(collectLibs)
} }
jar { build {
finalizedBy("reobfJar") dependsOn("reobfJar")
} }
publishing { publishing {

View File

@ -52,6 +52,19 @@ public interface ColumnDecorator {
} }
} }
default void fillDownSolid(DecoratorContext context, IChunk chunk, int x, int z, int from, int to, BlockState state) {
for (int dy = from; dy > to; dy--) { ;
replaceSolid(chunk, context.pos.setPos(x, dy, z), state);
}
}
static void replaceSolid(IChunk chunk, BlockPos pos, BlockState state) {
if (chunk.getBlockState(pos).isAir(chunk, pos)) {
return;
}
chunk.setBlockState(pos, state, false);
}
static float getNoise(float x, float z, int seed, float scale, float bias) { static float getNoise(float x, float z, int seed, float scale, float bias) {
return (variance.getValue(x, z, seed) * scale) + bias; return (variance.getValue(x, z, seed) * scale) + bias;
} }

View File

@ -38,7 +38,7 @@ public interface BiomeMap {
Biome getBeach(Cell cell); Biome getBeach(Cell cell);
Biome getCoast(Cell cell, Biome current); Biome getCoast(Cell cell);
Biome getRiver(Cell cell); Biome getRiver(Cell cell);

View File

@ -54,6 +54,7 @@ public class SimpleBiomeMap implements BiomeMap {
} }
} }
@Override
public Biome provideBiome(Cell cell, Levels levels) { public Biome provideBiome(Cell cell, Levels levels) {
TerrainType type = cell.terrain.getType(); TerrainType type = cell.terrain.getType();
if (type.isSubmerged() && cell.value > levels.water) { if (type.isSubmerged() && cell.value > levels.water) {
@ -78,7 +79,7 @@ public class SimpleBiomeMap implements BiomeMap {
} }
@Override @Override
public Biome getCoast(Cell cell, Biome current) { public Biome getCoast(Cell cell) {
int inland = land.getSize(cell); int inland = land.getSize(cell);
Biome[] coastal = coast.getSet(cell); Biome[] coastal = coast.getSet(cell);
int total = inland + coastal.length; int total = inland + coastal.length;
@ -86,7 +87,7 @@ public class SimpleBiomeMap implements BiomeMap {
if (index >= inland) { if (index >= inland) {
return coastal[index - inland]; return coastal[index - inland];
} }
return current; return DefaultBiomes.NONE;
} }
@Override @Override

View File

@ -28,6 +28,7 @@ package com.terraforged.mod.biome.modifier;
import com.terraforged.api.biome.modifier.BiomeModifier; import com.terraforged.api.biome.modifier.BiomeModifier;
import com.terraforged.core.cell.Cell; import com.terraforged.core.cell.Cell;
import com.terraforged.mod.biome.map.BiomeMap; import com.terraforged.mod.biome.map.BiomeMap;
import com.terraforged.mod.biome.map.defaults.DefaultBiomes;
import com.terraforged.mod.chunk.TerraContext; import com.terraforged.mod.chunk.TerraContext;
import com.terraforged.world.terrain.Terrains; import com.terraforged.world.terrain.Terrains;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
@ -57,7 +58,10 @@ public class CoastModifier implements BiomeModifier {
@Override @Override
public Biome modify(Biome in, Cell cell, int x, int z) { public Biome modify(Biome in, Cell cell, int x, int z) {
if (cell.terrain.isCoast()) { if (cell.terrain.isCoast()) {
return biomeMap.getCoast(cell, in); Biome coast = biomeMap.getCoast(cell);
if (coast != DefaultBiomes.NONE) {
return coast;
}
} }
return in; return in;
} }

View File

@ -69,6 +69,12 @@ public class TerraBiomeProvider extends BiomeProvider {
return getWorldLookup().getCell(x, z); return getWorldLookup().getCell(x, z);
} }
public Biome getBiome(int x, int z) {
try (Resource<Cell> resource = getWorldLookup().getCell(x, z, true)) {
return getBiome(resource.get(), x, z);
}
}
@Override @Override
public Biome getNoiseBiome(int x, int y, int z) { public Biome getNoiseBiome(int x, int y, int z) {
x = (x << 2); x = (x << 2);

View File

@ -96,7 +96,7 @@ public class ErosionDecorator implements ColumnDecorator {
erodeRock(context, chunk, x, y, z); erodeRock(context, chunk, x, y, z);
return; return;
} else { } else {
fillDown(context, chunk, x, z, y, y - 4, material); fillDownSolid(context, chunk, x, z, y, y - 4, material);
} }
} }
placeScree(chunk, context, x, y, z); placeScree(chunk, context, x, y, z);
@ -105,7 +105,7 @@ public class ErosionDecorator implements ColumnDecorator {
protected void erodeRock(DecoratorContext context, IChunk chunk, int dx, int y, int dz) { protected void erodeRock(DecoratorContext context, IChunk chunk, int dx, int y, int dz) {
int depth = 32; int depth = 32;
BlockState material = Blocks.GRAVEL.getDefaultState(); BlockState material = States.GRAVEL.get();
// find the uppermost layer of rock & record it's depth // find the uppermost layer of rock & record it's depth
for (int dy = 3; dy < 32; dy++) { for (int dy = 3; dy < 32; dy++) {
context.pos.setPos(dx, y - dy, dz); context.pos.setPos(dx, y - dy, dz);
@ -119,8 +119,7 @@ public class ErosionDecorator implements ColumnDecorator {
// fill downwards to the first rock layer // fill downwards to the first rock layer
for (int dy = 0; dy < depth; dy++) { for (int dy = 0; dy < depth; dy++) {
context.pos.setPos(dx, y - dy, dz); ColumnDecorator.replaceSolid(chunk, context.pos.setPos(dx, y - dy, dz), material);
chunk.setBlockState(context.pos, material, false);
} }
} }
@ -133,7 +132,7 @@ public class ErosionDecorator implements ColumnDecorator {
float sediment = context.cell.sediment * SEDIMENT_MODIFIER; float sediment = context.cell.sediment * SEDIMENT_MODIFIER;
float noise = context.climate.getRand().getValue(x, z, seed3) * SEDIMENT_NOISE; float noise = context.climate.getRand().getValue(x, z, seed3) * SEDIMENT_NOISE;
if (sediment + noise > SCREE_VALUE) { if (sediment + noise > SCREE_VALUE) {
fillDown(context, chunk, x, z, y, y - 2, States.GRAVEL.get()); fillDownSolid(context, chunk, x, z, y, y - 2, States.GRAVEL.get());
} }
} }

View File

@ -48,8 +48,7 @@ public class GeologyDecorator implements ColumnDecorator {
public void decorate(ChunkSurfaceBuffer buffer, DecoratorContext context, int x, int y, int z) { public void decorate(ChunkSurfaceBuffer buffer, DecoratorContext context, int x, int y, int z) {
int top = buffer.getSurfaceBottom(); int top = buffer.getSurfaceBottom();
geology.getGeology(context.biome).getStrata(x, z).downwards(x, top, z, context.depthBuffer.get(), (py, state) -> { geology.getGeology(context.biome).getStrata(x, z).downwards(x, top, z, context.depthBuffer.get(), (py, state) -> {
context.pos.setPos(x, py, z); ColumnDecorator.replaceSolid(buffer.getDelegate(), context.pos.setPos(x, py, z), state);
buffer.getDelegate().setBlockState(context.pos, state, false);
return true; return true;
}); });
} }

View File

@ -26,7 +26,7 @@ public class TerrainGenerator implements Generator.Terrain {
this.levels = generator.getContext().levels; this.levels = generator.getContext().levels;
this.terrain = generator.getContext().terrain; this.terrain = generator.getContext().terrain;
this.climate = generator.getContext().factory.getClimate(); this.climate = generator.getContext().factory.getClimate();
this.terrainHelper = new TerrainHelper(0.75F); this.terrainHelper = new TerrainHelper(0.75F, 4F);
} }
@Override @Override

View File

@ -31,6 +31,28 @@ public class SettingsHelper {
} }
} }
public static TerraSettings loadSettings(File file) {
TerraSettings settings = new TerraSettings();
try (Reader reader = new BufferedReader(new FileReader(file))) {
JsonElement data = new JsonParser().parse(reader);
CompoundNBT nbt = NBTHelper.fromJson(data);
if (NBTHelper.deserialize(nbt, settings)) {
return settings;
}
} catch (IOException e) {
e.printStackTrace();
}
try (Writer writer = new BufferedWriter(new FileWriter(file))) {
CompoundNBT tag = NBTHelper.serializeCompact(settings);
JsonElement json = NBTHelper.toJson(tag);
GSON.toJson(json, writer);
} catch (IOException e) {
e.printStackTrace();
}
return settings;
}
public static void exportDefaults(TerraSettings settings) { public static void exportDefaults(TerraSettings settings) {
CompoundNBT tag = NBTHelper.serializeCompact(settings); CompoundNBT tag = NBTHelper.serializeCompact(settings);
JsonElement json = NBTHelper.toJson(tag); JsonElement json = NBTHelper.toJson(tag);
@ -51,18 +73,10 @@ public class SettingsHelper {
} }
public static TerraSettings readDefaults() { public static TerraSettings readDefaults() {
TerraSettings settings = new TerraSettings();
if (DEFAULTS_FILE.exists()) { if (DEFAULTS_FILE.exists()) {
try (Reader reader = new BufferedReader(new FileReader(DEFAULTS_FILE))) { return loadSettings(DEFAULTS_FILE);
Log.info("Loading generator settings from json");
JsonElement json = new JsonParser().parse(reader);
CompoundNBT root = NBTHelper.fromJson(json);
NBTHelper.deserialize(root, settings);
} catch (Throwable t) {
t.printStackTrace();
}
} }
return settings; return new TerraSettings();
} }
public static TerraSettings getSettings(WorldInfo info) { public static TerraSettings getSettings(WorldInfo info) {

View File

@ -3,20 +3,16 @@ package com.terraforged.mod.chunk.settings.preset;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.terraforged.mod.Log; import com.terraforged.mod.Log;
import com.terraforged.mod.chunk.settings.SettingsHelper; import com.terraforged.mod.chunk.settings.SettingsHelper;
import com.terraforged.mod.chunk.settings.TerraSettings; import com.terraforged.mod.chunk.settings.TerraSettings;
import com.terraforged.mod.util.nbt.NBTHelper; import com.terraforged.mod.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -127,15 +123,8 @@ public class PresetManager implements Iterable<Preset> {
} }
String name = file.getName().substring(0, file.getName().length() - 5); String name = file.getName().substring(0, file.getName().length() - 5);
try (Reader reader = new BufferedReader(new FileReader(file))) { TerraSettings settings = SettingsHelper.loadSettings(file);
JsonElement data = new JsonParser().parse(reader); presets.add(new Preset(name, file, settings));
CompoundNBT nbt = NBTHelper.fromJson(data);
TerraSettings settings = new TerraSettings();
NBTHelper.deserialize(nbt, settings);
presets.add(new Preset(name, file, settings));
} catch (IOException e) {
e.printStackTrace();
}
} }
return new PresetManager(presets); return new PresetManager(presets);

View File

@ -11,7 +11,7 @@ public class TerraBoundSlider extends TerraSlider.Float {
private final String upper; private final String upper;
public TerraBoundSlider(String name, CompoundNBT value) { public TerraBoundSlider(String name, CompoundNBT value) {
this(name, value, 0.01F); this(name, value, 0.005F);
} }
public TerraBoundSlider(String name, CompoundNBT value, float pad) { public TerraBoundSlider(String name, CompoundNBT value, float pad) {

View File

@ -40,6 +40,7 @@ import com.terraforged.mod.util.nbt.NBTHelper;
import com.terraforged.n2d.util.NoiseUtil; import com.terraforged.n2d.util.NoiseUtil;
import com.terraforged.world.GeneratorContext; import com.terraforged.world.GeneratorContext;
import com.terraforged.world.continent.MutableVeci; import com.terraforged.world.continent.MutableVeci;
import com.terraforged.world.continent.SpawnType;
import com.terraforged.world.heightmap.Levels; import com.terraforged.world.heightmap.Levels;
import com.terraforged.world.terrain.Terrains; import com.terraforged.world.terrain.Terrains;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -204,7 +205,9 @@ public class Preview extends Button {
GeneratorContext context = GeneratorContext.createNoCache(Terrains.create(settings), settings); GeneratorContext context = GeneratorContext.createNoCache(Terrains.create(settings), settings);
MutableVeci center = new MutableVeci(); MutableVeci center = new MutableVeci();
context.factory.getHeightmap().getContinent().getNearestCenter(offsetX, offsetZ, center); if (settings.world.properties.spawnType == SpawnType.CONTINENT_CENTER) {
context.factory.getHeightmap().getContinent().getNearestCenter(offsetX, offsetZ, center);
}
TileGenerator renderer = TileGenerator.builder() TileGenerator renderer = TileGenerator.builder()
.pool(threadPool) .pool(threadPool)

View File

@ -59,9 +59,15 @@ public class TerrainHelper {
); );
private final float radius; private final float radius;
private final float overhang;
private final float overhang2;
public TerrainHelper(float radius) { // base - the size of the base built up around a piece as a percentage of its bounding box size
this.radius = radius; // overhang - the amount of overhead overhang to be cut out
public TerrainHelper(float base, float cutout) {
this.radius = base;
this.overhang = cutout;
this.overhang2 = cutout * cutout;
} }
public void flatten(IWorld world, IChunk chunk) { public void flatten(IWorld world, IChunk chunk) {
@ -148,7 +154,22 @@ public class TerrainHelper {
if (highest != null) { if (highest != null) {
MutableBoundingBox bounds = highest.getBoundingBox(); MutableBoundingBox bounds = highest.getBoundingBox();
for (int dy = bounds.minY + highestOffset; dy <= surface; dy++) { int minY = bounds.minY + highestOffset;
int maxY = minY + bounds.getYSize();
if (maxY <= surface) {
// gets weaker the further from the center of the piece
float dist = getCenterDistance2(x, z, bounds);
float distAlpha = 1F - NoiseUtil.clamp(dist / overhang2, 0, 1);
// gets weaker the more material is overhead creating the inverse cutout (ie overhang)
float depth = surface - maxY;
float depthAlpha = 1F - NoiseUtil.clamp(depth / overhang, 0, 1);
maxY += NoiseUtil.round(depthAlpha * distAlpha * overhang);
}
for (int dy = minY; dy <= maxY; dy++) {
pos.setPos(dx, dy, dz); pos.setPos(dx, dy, dz);
chunk.setBlockState(pos, Blocks.AIR.getDefaultState(), false); chunk.setBlockState(pos, Blocks.AIR.getDefaultState(), false);
} }
@ -164,6 +185,14 @@ public class TerrainHelper {
return NoiseUtil.lerp(surface, level, alpha); return NoiseUtil.lerp(surface, level, alpha);
} }
private float getCenterDistance2(int x, int z, MutableBoundingBox bounds) {
float cx = bounds.minX + (bounds.getXSize() / 2F);
float cz = bounds.minZ + (bounds.getZSize() / 2F);
float dx = cx - x;
float dz = cz - z;
return dx * dx + dz * dz;
}
private static void collectPiece(StructurePiece structurepiece, List<StructurePiece> list) { private static void collectPiece(StructurePiece structurepiece, List<StructurePiece> list) {
if (structurepiece instanceof AbstractVillagePiece) { if (structurepiece instanceof AbstractVillagePiece) {
AbstractVillagePiece piece = (AbstractVillagePiece) structurepiece; AbstractVillagePiece piece = (AbstractVillagePiece) structurepiece;

View File

@ -132,7 +132,11 @@ public class TerraCommand {
try (Resource<Cell> cell = biomeProvider.lookupPos(pos.getX(), pos.getZ())) { try (Resource<Cell> cell = biomeProvider.lookupPos(pos.getX(), pos.getZ())) {
Biome biome = biomeProvider.getBiome(cell.get(), pos.getX(), pos.getZ()); Biome biome = biomeProvider.getBiome(cell.get(), pos.getX(), pos.getZ());
context.getSource().sendFeedback( context.getSource().sendFeedback(
new StringTextComponent("Terrain=" + cell.get().terrain.getName() + ", Biome=" + biome.getRegistryName()), new StringTextComponent(
"Terrain=" + cell.get().terrain.getName()
+ ", Biome=" + biome.getRegistryName()
+ ", BiomeType=" + cell.get().biomeType.name()
),
false false
); );
} }

View File

@ -27,6 +27,9 @@ public class BiomeSearchTask extends ChunkGeneratorSearch {
@Override @Override
public boolean test(BlockPos pos) { public boolean test(BlockPos pos) {
biomeProvider.getWorldLookup().applyCell(cell, pos.getX(), pos.getZ()); biomeProvider.getWorldLookup().applyCell(cell, pos.getX(), pos.getZ());
return biomeProvider.getBiome(cell, pos.getX(), pos.getZ()) == biome; if (biomeProvider.getBiome(cell, pos.getX(), pos.getZ()) == biome) {
return biomeProvider.getBiome(pos.getX(), pos.getZ()) == biome;
}
return false;
} }
} }

View File

@ -114,12 +114,13 @@ public class NBTHelper {
return tag; return tag;
} }
public static void deserialize(CompoundNBT settings, Object object) { public static boolean deserialize(CompoundNBT settings, Object object) {
try { try {
NBTReader reader = new NBTReader(settings); NBTReader reader = new NBTReader(settings);
reader.writeTo(object); return reader.writeTo(object);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
return false;
} }
} }
} }