diff --git a/TerraForgedMod/build.gradle b/TerraForgedMod/build.gradle index 928ead1..923c40d 100644 --- a/TerraForgedMod/build.gradle +++ b/TerraForgedMod/build.gradle @@ -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 diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FirForest.java b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FirForest.java new file mode 100644 index 0000000..da72855 --- /dev/null +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FirForest.java @@ -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; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FlowerPlains.java b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FlowerPlains.java new file mode 100644 index 0000000..3adca77 --- /dev/null +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FlowerPlains.java @@ -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; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ModBiomes.java b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ModBiomes.java index 793bd52..d2ded1b 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ModBiomes.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ModBiomes.java @@ -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(); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java index f36058c..121472a 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java @@ -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; } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java b/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java index c105bdd..829a6d9 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java @@ -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); + } + } + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java index 95c511a..a54c154 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java @@ -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; } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java index b7785a3..09d36ff 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java @@ -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 consumer) { try (ObjectPool.Item 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))); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java index 3de3577..5f62f0b 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java @@ -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); } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java index 61ed89c..7a480e0 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java @@ -25,7 +25,7 @@ public abstract class PoissonDecorator extends Placement { @Override public final > boolean place(IWorld world, ChunkGenerator generator, Random random, BlockPos pos, PoissonConfig config, ConfiguredFeature 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 { 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 { } 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); - } - context.density = module; + 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; } }