set grass blocks to not snowy when eroding snow

This commit is contained in:
dags- 2020-04-02 22:11:45 +01:00
parent 66c2a318cd
commit 5121a235f0
10 changed files with 205 additions and 34 deletions

View File

@ -36,7 +36,7 @@ minecraft {
workingDirectory project.file("run/client")
property "forge.logging.markers", "SCAN,REGISTRIES,REGISTRYDUMP"
property "forge.logging.console.level", "debug"
jvmArgs "-Xmx8G", "-Xms6G", "-Ddev", "-DvanillaBiomes"
jvmArgs "-Xmx8G", "-Xms6G", "-Ddev"
mods {
terraforged {
source sourceSets.main

View File

@ -0,0 +1,61 @@
package com.terraforged.mod.biome;
import com.terraforged.api.biome.BiomeVariant;
import net.minecraft.entity.EntityClassification;
import net.minecraft.entity.EntityType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.biome.DefaultBiomeFeatures;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.structure.MineshaftConfig;
import net.minecraft.world.gen.feature.structure.MineshaftStructure;
import net.minecraft.world.gen.feature.structure.VillageConfig;
import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder;
public class FirForest extends BiomeVariant {
public FirForest() {
super((new Biome.Builder().surfaceBuilder(SurfaceBuilder.GIANT_TREE_TAIGA, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(Biome.RainType.RAIN).category(Biome.Category.TAIGA).depth(0.2F).scale(0.2F).temperature(0.25F).downfall(0.8F).waterColor(4159204).waterFogColor(329011).parent(null)));
this.addStructure(Feature.VILLAGE.withConfiguration(new VillageConfig("village/taiga/town_centers", 6)));
this.addStructure(Feature.PILLAGER_OUTPOST.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG));
this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL)));
this.addStructure(Feature.STRONGHOLD.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG));
DefaultBiomeFeatures.addCarvers(this);
DefaultBiomeFeatures.addStructures(this);
DefaultBiomeFeatures.addMonsterRooms(this);
DefaultBiomeFeatures.addTaigaLargeFerns(this);
DefaultBiomeFeatures.addStoneVariants(this);
DefaultBiomeFeatures.addOres(this);
DefaultBiomeFeatures.addSedimentDisks(this);
DefaultBiomeFeatures.addTaigaConifers(this);
DefaultBiomeFeatures.addDefaultFlowers(this);
DefaultBiomeFeatures.addTaigaGrassAndMushrooms(this);
DefaultBiomeFeatures.addDenseGrass(this);
DefaultBiomeFeatures.addReedsAndPumpkins(this);
DefaultBiomeFeatures.addBerryBushes(this);
DefaultBiomeFeatures.addFreezeTopLayer(this);
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.SHEEP, 12, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.PIG, 10, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.CHICKEN, 10, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.COW, 8, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.WOLF, 8, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.RABBIT, 4, 2, 3));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.FOX, 8, 2, 4));
this.addSpawn(EntityClassification.AMBIENT, new Biome.SpawnListEntry(EntityType.BAT, 10, 8, 8));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SPIDER, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE, 95, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE_VILLAGER, 5, 1, 1));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SKELETON, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.CREEPER, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SLIME, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ENDERMAN, 10, 1, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.WITCH, 5, 1, 1));
this.setRegistryName("terraforged", "fir_forest");
}
@Override
public Biome getBase() {
return Biomes.TAIGA;
}
}

View File

@ -0,0 +1,58 @@
package com.terraforged.mod.biome;
import com.google.common.collect.ImmutableList;
import com.terraforged.api.biome.BiomeVariant;
import net.minecraft.entity.EntityClassification;
import net.minecraft.entity.EntityType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.biome.DefaultBiomeFeatures;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.MultipleWithChanceRandomFeatureConfig;
import net.minecraft.world.gen.feature.structure.MineshaftConfig;
import net.minecraft.world.gen.feature.structure.MineshaftStructure;
import net.minecraft.world.gen.placement.FrequencyConfig;
import net.minecraft.world.gen.placement.Placement;
import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder;
public class FlowerPlains extends BiomeVariant {
public FlowerPlains() {
super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.DEFAULT, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(Biome.RainType.RAIN).category(Biome.Category.FOREST).depth(0.1F).scale(0.4F).temperature(0.7F).downfall(0.8F).waterColor(4159204).waterFogColor(329011).parent("forest"));
this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL)));
this.addStructure(Feature.STRONGHOLD.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG));
DefaultBiomeFeatures.addCarvers(this);
DefaultBiomeFeatures.addStructures(this);
DefaultBiomeFeatures.addMonsterRooms(this);
this.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.RANDOM_RANDOM_SELECTOR.withConfiguration(new MultipleWithChanceRandomFeatureConfig(ImmutableList.of(Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.LILAC_CONFIG), Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.ROSE_BUSH_CONFIG), Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.PEONY_CONFIG), Feature.FLOWER.withConfiguration(DefaultBiomeFeatures.LILY_OF_THE_VALLEY_CONFIG)), 2)).withPlacement(Placement.COUNT_HEIGHTMAP_32.configure(new FrequencyConfig(5))));
DefaultBiomeFeatures.addStoneVariants(this);
DefaultBiomeFeatures.addOres(this);
this.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.FLOWER.withConfiguration(DefaultBiomeFeatures.FOREST_FLOWER_CONFIG).withPlacement(Placement.COUNT_HEIGHTMAP_32.configure(new FrequencyConfig(100))));
DefaultBiomeFeatures.addSparseGrass(this);
DefaultBiomeFeatures.addMushrooms(this);
DefaultBiomeFeatures.addReedsAndPumpkins(this);
DefaultBiomeFeatures.addFreezeTopLayer(this);
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.SHEEP, 12, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.PIG, 10, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.CHICKEN, 10, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.COW, 8, 4, 4));
this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.RABBIT, 4, 2, 3));
this.addSpawn(EntityClassification.AMBIENT, new Biome.SpawnListEntry(EntityType.BAT, 10, 8, 8));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SPIDER, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE, 95, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE_VILLAGER, 5, 1, 1));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SKELETON, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.CREEPER, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SLIME, 100, 4, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ENDERMAN, 10, 1, 4));
this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.WITCH, 5, 1, 1));
setRegistryName("terraforged", "flower_plains");
}
@Override
public Biome getBase() {
return Biomes.FLOWER_FOREST;
}
}

View File

@ -47,6 +47,8 @@ public class ModBiomes {
public static final Biome TAIGA_SCRUB = register(new TaigaScrub());
public static final Biome WARM_BEACH = register(new WarmBeach());
public static final Biome MARSHLAND = register(new Marshland());
// public static final Biome FIR_FOREST = register(new FirForest());
// public static final Biome FLOWER_PLAINS = register(new FlowerPlains());
private static Biome register(BiomeVariant biome) {
biomes.add(biome);
@ -59,6 +61,9 @@ public class ModBiomes {
event.getRegistry().register(biome);
BiomeDictionary.makeBestGuess(biome);
BiomeDictionary.addTypes(biome, BiomeDictionary.Type.OVERWORLD);
if (BiomeDictionary.getTypes(biome.getBase()).contains(BiomeDictionary.Type.RARE)) {
BiomeDictionary.addTypes(biome, BiomeDictionary.Type.RARE);
}
});
biomes.clear();
biomes.trimToSize();

View File

@ -90,7 +90,7 @@ public class BiomeHelper {
// don't use BiomeDictionary with transient biomes
if (ForgeRegistries.BIOMES.containsKey(biome.getRegistryName())) {
if (BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.RARE)) {
weight = 2;
weight = 1;
}
}

View File

@ -32,6 +32,8 @@ import com.terraforged.mod.decorator.base.ErosionDecorator;
import me.dags.noise.source.Rand;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.GrassBlock;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
@ -78,7 +80,7 @@ public class SnowEroder extends ErosionDecorator {
context.pos.setPos(x, y + dy, z);
BlockState state = chunk.getBlockState(context.pos);
if (!predicate.test(state) || state.getBlock() == Blocks.SNOW) {
chunk.setBlockState(context.pos, Blocks.AIR.getDefaultState(), false);
erodeSnow(chunk, context.pos);
}
}
}
@ -90,4 +92,16 @@ public class SnowEroder extends ErosionDecorator {
|| (steepness > SNOW_ROCK_STEEPNESS && height > SNOW_ROCK_HEIGHT)
|| super.erodeDirt(x, z, steepness, height);
}
private void erodeSnow(IChunk chunk, BlockPos.Mutable pos) {
chunk.setBlockState(pos, Blocks.AIR.getDefaultState(), false);
if (pos.getY() > 0) {
pos.setY(pos.getY() - 1);
BlockState below = chunk.getBlockState(pos);
if (below.has(GrassBlock.SNOWY)) {
chunk.setBlockState(pos, below.with(GrassBlock.SNOWY, false), false);
}
}
}
}

View File

@ -14,34 +14,38 @@ import net.minecraft.world.gen.WorldGenRegion;
public class BiomeVariance implements Module {
private final ChunkReader chunk;
public static float MIN_FADE = 0.05F;
public BiomeVariance(ChunkReader chunk) {
private final ChunkReader chunk;
private final float fade;
private final float range;
public BiomeVariance(ChunkReader chunk, float fade) {
this.chunk = chunk;
this.fade = fade;
this.range = fade - MIN_FADE;
}
@Override
public float getValue(float x, float y) {
int dx = ((int) x) & 15;
int dz = ((int) y) & 15;
Cell<?> cell = chunk.getCell(dx, dz);
return NoiseUtil.map(1 - cell.biomeEdge, 0.05F, 0.25F, 0.2F);
Cell<?> cell = chunk.getCell((int) x, (int) y);
return NoiseUtil.map(1 - cell.biomeEdge, MIN_FADE, fade, range);
}
public static Module of(IWorld world) {
public static Module of(IWorld world, float fade) {
if (world instanceof RegionDelegate) {
WorldGenRegion region = ((RegionDelegate) world).getRegion();
IChunk chunk = region.getChunk(region.getMainChunkX(), region.getMainChunkZ());
return of(chunk);
return of(chunk, fade);
}
return Source.ONE;
}
public static Module of(IChunk chunk) {
public static Module of(IChunk chunk, float fade) {
BiomeContainer container = chunk.getBiomes();
if (container instanceof TerraContainer) {
ChunkReader reader = ((TerraContainer) container).getChunkReader();
return new BiomeVariance(reader);
return new BiomeVariance(reader, fade);
}
return Source.ONE;
}

View File

@ -1,6 +1,7 @@
package com.terraforged.mod.feature.decorator.poisson;
import com.terraforged.core.util.concurrent.ObjectPool;
import me.dags.noise.Source;
import me.dags.noise.util.NoiseUtil;
import me.dags.noise.util.Vec2f;
@ -17,6 +18,7 @@ public class Poisson {
private final int radius;
private final int radius2;
private final float halfRadius;
private final int maxDistance;
private final int regionSize;
private final int gridSize;
@ -27,14 +29,18 @@ public class Poisson {
int size = 48;
this.radius = radius;
this.radius2 = radius * radius;
int halfRadius = radius / 2;
this.halfRadius = radius / 2F;
this.maxDistance = radius * 2;
this.regionSize = size - halfRadius;
this.regionSize = size - radius;
this.cellSize = radius / NoiseUtil.SQRT2;
this.gridSize = (int) Math.ceil(regionSize / cellSize);
this.pool = new ObjectPool<>(3, () -> new Vec2f[gridSize][gridSize]);
}
public int getRadius() {
return radius;
}
public void visit(int chunkX, int chunkZ, PoissonContext context, BiConsumer<Integer, Integer> consumer) {
try (ObjectPool.Item<Vec2f[][]> grid = pool.get()) {
clear(grid.getValue());
@ -57,8 +63,8 @@ public class Poisson {
for (int i = 0; i < samples; i++) {
float angle = context.random.nextFloat() * NoiseUtil.PI2;
float distance = radius + (context.random.nextFloat() * maxDistance);
float x = px + NoiseUtil.sin(angle) * distance;
float z = pz + NoiseUtil.cos(angle) * distance;
float x = halfRadius + px + NoiseUtil.sin(angle) * distance;
float z = halfRadius + pz + NoiseUtil.cos(angle) * distance;
if (valid(x, z, grid, context)) {
Vec2f vec = new Vec2f(x, z);
visit(vec, context, consumer);
@ -122,7 +128,7 @@ public class Poisson {
public static void main(String[] args) {
int size = 512;
int radius = 10;
int radius = 6;
int chunkSize = 16;
int chunks = size / chunkSize;
@ -130,13 +136,19 @@ public class Poisson {
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
Poisson poisson = new Poisson(radius);
PoissonContext context = new PoissonContext(213, new Random());
context.density = Source.simplex(213, 100, 1).scale(2).bias(0);
long time = 0L;
long count = 0L;
int chunkX = 342;
int chunkZ = 546;
for (int cz = 0; cz < chunks; cz++) {
for (int cx = 0; cx < chunks; cx++) {
long start = System.nanoTime();
poisson.visit(cx, cz, context, (x, z) -> {
poisson.visit(chunkX + cx, chunkZ + cz, context, (x, z) -> {
x -= chunkX << 4;
z -= chunkZ << 4;
if (x < 0 || x >= image.getWidth() || z < 0 || z >= image.getHeight()) {
return;
}
@ -147,8 +159,8 @@ public class Poisson {
}
}
double avg = (double) time / count;
System.out.println(avg + "ns");
double avg = (double) (time / count) / 1000000;
System.out.println(avg + "ms");
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(image)));

View File

@ -8,11 +8,17 @@ import net.minecraft.world.gen.placement.IPlacementConfig;
public class PoissonConfig implements IPlacementConfig {
public final int radius;
public final float biomeFade;
public final int variance;
public final float min;
public final float max;
public PoissonConfig(int radius, int variance) {
public PoissonConfig(int radius, float biomeFade, int variance, float min, float max) {
this.radius = radius;
this.biomeFade = biomeFade;
this.variance = variance;
this.min = min;
this.max = max;
}
@Override
@ -20,14 +26,20 @@ public class PoissonConfig implements IPlacementConfig {
return new Dynamic<>(ops, ops.createMap(
ImmutableMap.of(
ops.createString("radius"), ops.createInt(radius),
ops.createString("variance_scale"), ops.createInt(variance)
ops.createString("fade"), ops.createFloat(biomeFade),
ops.createString("scale"), ops.createInt(variance),
ops.createString("min"), ops.createFloat(min),
ops.createString("max"), ops.createFloat(max)
))
);
}
public static PoissonConfig deserialize(Dynamic<?> dynamic) {
int radius = dynamic.get("radius").asInt(4);
int variance = dynamic.get("variance_scale").asInt(0);
return new PoissonConfig(radius, variance);
float biomeFade = dynamic.get("fade").asFloat(0.2F);
int variance = dynamic.get("scale").asInt(0);
float min = dynamic.get("min").asFloat(0F);
float max = dynamic.get("max").asFloat(1F);
return new PoissonConfig(radius, biomeFade, variance, min, max);
}
}

View File

@ -25,7 +25,7 @@ public abstract class PoissonDecorator extends Placement<PoissonConfig> {
@Override
public final <FC extends IFeatureConfig, F extends Feature<FC>> boolean place(IWorld world, ChunkGenerator<?> generator, Random random, BlockPos pos, PoissonConfig config, ConfiguredFeature<FC, F> feature) {
int radius = Math.max(2, Math.min(30, config.radius));
int radius = Math.max(1, Math.min(30, config.radius));
Poisson poisson = getInstance(radius);
PoissonVisitor visitor = new PoissonVisitor(this, feature, world, generator, random, pos);
setVariance(world, visitor, config);
@ -44,7 +44,7 @@ public abstract class PoissonDecorator extends Placement<PoissonConfig> {
private Poisson getInstance(int radius) {
synchronized (lock) {
if (instance == null) {
if (instance == null || instance.getRadius() != radius) {
instance = new Poisson(radius);
}
return instance;
@ -52,13 +52,18 @@ public abstract class PoissonDecorator extends Placement<PoissonConfig> {
}
private void setVariance(IWorld world, PoissonContext context, PoissonConfig config) {
Module module = BiomeVariance.of(world);
if (module != Source.ONE) {
if (config.variance > 0) {
Module variance = Source.simplex((int) world.getSeed(), config.variance, 1).scale(1.5);
module = module.mult(variance);
Module module = Source.ONE;
if (config.biomeFade > 0.075F) {
module = BiomeVariance.of(world, config.biomeFade);
}
if (config.variance > 0) {
module = module.mult(Source.simplex(context.seed, config.variance, 1)
.scale(config.max - config.min)
.bias(config.min));
}
context.density = module;
}
}
}