From c44145c712111d65a26ed6f935b4abbcd5f16913 Mon Sep 17 00:00:00 2001 From: TheDeathlyCow Date: Thu, 30 Nov 2023 02:20:26 -1000 Subject: [PATCH] icicle heights and density --- .../world/gen/feature/IcicleFeature.java | 105 +++++++++++++++--- .../configured_feature/icicle_cluster.json | 16 +-- 2 files changed, 96 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/github/thedeathlycow/frostiful/world/gen/feature/IcicleFeature.java b/src/main/java/com/github/thedeathlycow/frostiful/world/gen/feature/IcicleFeature.java index d6798344..924905ea 100644 --- a/src/main/java/com/github/thedeathlycow/frostiful/world/gen/feature/IcicleFeature.java +++ b/src/main/java/com/github/thedeathlycow/frostiful/world/gen/feature/IcicleFeature.java @@ -6,6 +6,8 @@ import net.minecraft.block.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.floatprovider.ClampedNormalFloatProvider; import net.minecraft.util.math.floatprovider.FloatProvider; import net.minecraft.util.math.floatprovider.UniformFloatProvider; import net.minecraft.util.math.intprovider.IntProvider; @@ -14,6 +16,8 @@ import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldView; +import net.minecraft.world.gen.feature.DripstoneClusterFeature; +import net.minecraft.world.gen.feature.DripstoneClusterFeatureConfig; import net.minecraft.world.gen.feature.Feature; import net.minecraft.world.gen.feature.FeatureConfig; import net.minecraft.world.gen.feature.util.CaveSurface; @@ -41,8 +45,11 @@ public boolean generate(FeatureContext context) { int xRadius = config.radius.get(random); int zRadius = config.radius.get(random); + float density = config.density.get(random); + int icicleHeight = config.icicleHeight.get(random); + // generate - generate(worldAccess, random, origin, xRadius, zRadius, config); + generate(worldAccess, random, origin, xRadius, zRadius, density, icicleHeight, config); return true; } @@ -53,16 +60,17 @@ private void generate( BlockPos origin, int xRadius, int zRadius, + float density, + int icicleHeight, IcicleFeatureConfig config ) { BlockPos pos; - float ceilingDensity = config.density.get(random); - float floorDensity = config.density.get(random); for (int x = -xRadius; x < xRadius; x++) { for (int z = -zRadius; z < zRadius; z++) { pos = origin.add(x, 0, z); - generateColumn(world, random, pos, ceilingDensity, floorDensity, config); + double icicleChance = this.icicleChance(xRadius, zRadius, x, z, config); + generateColumn(world, random, pos, x, z, density, icicleChance, icicleHeight, config); } } } @@ -71,8 +79,10 @@ private void generateColumn( WorldAccess world, Random random, BlockPos position, - float ceilingDensity, - float floorDensity, + int localX, int localZ, + float density, + double icicleChance, + int icicleHeight, IcicleFeatureConfig config ) { @@ -94,20 +104,40 @@ private void generateColumn( return; } + boolean shouldGenerateCeiling = random.nextDouble() < icicleChance; + boolean shouldGenerateFloor = random.nextDouble() < icicleChance; + + + int floorIcicleLength = 0; + int ceilingIcicleLength = 0; + + // build ice layers - if (ceilingHeight.isPresent() && random.nextDouble() < ceilingDensity && !this.isLava(world, position.withY(ceilingHeight.getAsInt()))) { + if (ceilingHeight.isPresent() && shouldGenerateCeiling && !this.isLava(world, position.withY(ceilingHeight.getAsInt()))) { int thickness = config.packedIceBlockLayerThickness.get(random); this.placePackedIceBlocks(world, position.withY(ceilingHeight.getAsInt()), thickness, Direction.UP); + ceilingIcicleLength = getHeight( + random, + localX, localZ, + density, + icicleHeight, + config + ); } - if (floorHeight.isPresent() && random.nextDouble() < floorDensity && !this.isLava(world, position.withY(floorHeight.getAsInt()))) { + if (floorHeight.isPresent() && shouldGenerateFloor && !this.isLava(world, position.withY(floorHeight.getAsInt()))) { int thickness = config.packedIceBlockLayerThickness.get(random); this.placePackedIceBlocks(world, position.withY(floorHeight.getAsInt()), thickness, Direction.DOWN); + floorIcicleLength = getHeight( + random, + localX, localZ, + density, + icicleHeight, + config + ); } // place icicles - int floorIcicleLength = config.icicleHeight.get(random); - int ceilingIcicleLength = config.icicleHeight.get(random); boolean merge = false; // adjust icicle heights if they would intersect with each other or terrain @@ -128,7 +158,8 @@ private void generateColumn( } } - if (ceilingHeight.isPresent() && random.nextDouble() < ceilingDensity) { + // place icicles + if (ceilingHeight.isPresent() && shouldGenerateCeiling && ceilingIcicleLength > 0) { IcicleHelper.generateIcicle( world, position.withY(ceilingHeight.getAsInt() - 1), @@ -137,7 +168,7 @@ private void generateColumn( merge ); } - if (floorHeight.isPresent() && random.nextDouble() < floorDensity) { + if (floorHeight.isPresent() && shouldGenerateFloor && floorIcicleLength > 0) { IcicleHelper.generateIcicle( world, position.withY(floorHeight.getAsInt() + 1), @@ -162,13 +193,49 @@ private void placePackedIceBlocks(WorldAccess world, BlockPos pos, int thickness } } + private int getHeight(Random random, int localX, int localZ, float density, int maxHeight, IcicleFeatureConfig config) { + if (random.nextFloat() > density) { + return 0; + } + int absoluteDistanceManhattan = Math.abs(localX) + Math.abs(localZ); + float mean = MathHelper.clampedMap( + absoluteDistanceManhattan, + 1.0f, + config.maxDistanceFromCenterAffectingHeightBias, + maxHeight / 2.0f, + 1.0f + ); + return (int) clampedGaussian(random, 1.0f, maxHeight, mean, config.heightDeviation); + } + + private static float clampedGaussian(Random random, float min, float max, float mean, float deviation) { + return ClampedNormalFloatProvider.get(random, mean, deviation, min, max); + } + + private double icicleChance(int radiusX, int radiusZ, int localX, int localZ, IcicleFeatureConfig config) { + int distanceToEdgeX = radiusX - Math.abs(localX); + int distanceToEdgeZ = radiusZ - Math.abs(localZ); + int minDistanceToEdge = Math.min(distanceToEdgeX, distanceToEdgeZ); + return MathHelper.clampedMap( + minDistanceToEdge, + 0.0, IcicleFeatureConfig.MAX_DIST_FROM_CENTER_AFFECTING_COLUMN_CHANCE, + IcicleFeatureConfig.CHANCE_OF_COLUMN_AT_MAX_DISTANCE, 1.0 + ); + } + public record IcicleFeatureConfig( IntProvider icicleHeight, IntProvider radius, FloatProvider density, int floorToCeilingSearchRange, - IntProvider packedIceBlockLayerThickness + IntProvider packedIceBlockLayerThickness, + int heightDeviation, + int maxDistanceFromCenterAffectingHeightBias ) implements FeatureConfig { + + private static final double MAX_DIST_FROM_CENTER_AFFECTING_COLUMN_CHANCE = 3.0; + private static final double CHANCE_OF_COLUMN_AT_MAX_DISTANCE = 0.1; + public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( IntProvider.createValidatingCodec(0, 10) @@ -181,7 +248,7 @@ public record IcicleFeatureConfig( .forGetter(config -> config.radius), FloatProvider.createValidatedCodec(0f, 1f) .fieldOf("density") - .orElse(UniformFloatProvider.create(0.3f, 0.7f)) + .orElse(UniformFloatProvider.create(0.1f, 0.4f)) .forGetter(config -> config.density), Codec.intRange(1, 32) .fieldOf("floor_to_ceiling_search_range") @@ -190,7 +257,15 @@ public record IcicleFeatureConfig( IntProvider.createValidatingCodec(1, 32) .fieldOf("packed_ice_layer_thickness") .orElse(UniformIntProvider.create(1, 4)) - .forGetter(config -> config.packedIceBlockLayerThickness) + .forGetter(config -> config.packedIceBlockLayerThickness), + Codec.intRange(1, 64) + .fieldOf("height_deviation") + .orElse(3) + .forGetter(config -> config.heightDeviation), + Codec.intRange(1, 64) + .fieldOf("max_distance_from_center_affecting_height_bias") + .orElse(8) + .forGetter(config -> config.maxDistanceFromCenterAffectingHeightBias) ).apply(instance, IcicleFeatureConfig::new) ); diff --git a/src/main/resources/data/frostiful/worldgen/configured_feature/icicle_cluster.json b/src/main/resources/data/frostiful/worldgen/configured_feature/icicle_cluster.json index d54d37e4..d4b45389 100644 --- a/src/main/resources/data/frostiful/worldgen/configured_feature/icicle_cluster.json +++ b/src/main/resources/data/frostiful/worldgen/configured_feature/icicle_cluster.json @@ -4,8 +4,8 @@ "icicle_height": { "type": "minecraft:uniform", "value": { - "min_inclusive": 1, - "max_inclusive": 4 + "min_inclusive": 3, + "max_inclusive": 6 } }, "radius": { @@ -15,13 +15,7 @@ "max_inclusive": 8 } }, - "density": { - "type": "minecraft:uniform", - "value": { - "min_inclusive": 0.3, - "max_inclusive": 0.7 - } - }, + "density": 1.0, "floor_to_ceiling_search_range": 12, "packed_ice_layer_thickness": { "type": "minecraft:uniform", @@ -29,6 +23,8 @@ "min_inclusive": 4, "max_inclusive": 7 } - } + }, + "height_deviation": 3, + "max_distance_from_center_affecting_height_bias": 8 } }