From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Wed, 2 Mar 2016 02:17:54 -0600
Subject: [PATCH] Flat bedrock generator settings

Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>

diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 275c9e6c60dc78bc2acc6fc8a78727d2030babdd..fa620165fcdd71ee596142260b77688a42b99b78 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -462,5 +462,10 @@ public class PaperWorldConfig {
     private void pillagerSettings() {
         disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols);
     }
+
+    public boolean generateFlatBedrock = false;
+    private void generatorSettings() {
+        generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", this.generateFlatBedrock);
+    }
 }
 
diff --git a/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java b/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java
index 514493f20bcd0a697d6787e11ec7042e601e1de2..66379a83e7fe7b9d1262e1ef4a7fa986adeb82ba 100644
--- a/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java
+++ b/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java
@@ -54,6 +54,50 @@ public class SurfaceRuleData {
         return overworldLike(true, false, true);
     }
 
+    // Paper start
+    // Taken from SurfaceRules$VerticalGradientConditionSource
+    private final record PaperBedrockConditionSource(String randomName, VerticalAnchor trueAtAndBelow, VerticalAnchor falseAtAndAbove, boolean invert) implements SurfaceRules.ConditionSource {
+        @Override
+        public com.mojang.serialization.Codec<? extends SurfaceRules.ConditionSource> codec() {
+            return CODEC;
+        }
+
+        @Override
+        public SurfaceRules.Condition apply(SurfaceRules.Context context) {
+            boolean hasFlatBedrock = context.context.getWorld().paperConfig.generateFlatBedrock;
+            int trueAtY = this.trueAtAndBelow().resolveY(context.context);
+            int falseAtY = this.falseAtAndAbove().resolveY(context.context);
+
+            int y = invert ? Math.max(falseAtY, trueAtY) - 1 : Math.min(falseAtY, trueAtY) ;
+            final int i = hasFlatBedrock ? y : trueAtY;
+            final int j = hasFlatBedrock ? y : falseAtY;
+            final net.minecraft.world.level.levelgen.PositionalRandomFactory positionalRandomFactory = context.system.getOrCreateRandomFactory(new net.minecraft.resources.ResourceLocation(this.randomName()));
+
+            class VerticalGradientCondition extends SurfaceRules.LazyYCondition {
+                VerticalGradientCondition(SurfaceRules.Context context) {
+                    super(context);
+                }
+
+                @Override
+                protected boolean compute() {
+                    int y = this.context.blockY;
+                    if (y <= i) {
+                        return true;
+                    } else if (y >= j) {
+                        return false;
+                    } else {
+                        double d = net.minecraft.util.Mth.map((double) y, (double) i, (double) j, 1.0D, 0.0D);
+                        net.minecraft.world.level.levelgen.RandomSource randomSource = positionalRandomFactory.at(this.context.blockX, i, this.context.blockZ);
+                        return (double) randomSource.nextFloat() < d;
+                    }
+                }
+            }
+
+            return new VerticalGradientCondition(context);
+        }
+    }
+    // Paper end
+
     public static SurfaceRules.RuleSource overworldLike(boolean surface, boolean bedrockRoof, boolean bedrockFloor) {
         SurfaceRules.ConditionSource conditionSource = SurfaceRules.yBlockCheck(VerticalAnchor.absolute(97), 2);
         SurfaceRules.ConditionSource conditionSource2 = SurfaceRules.yBlockCheck(VerticalAnchor.absolute(256), 0);
@@ -82,11 +126,11 @@ public class SurfaceRuleData {
         SurfaceRules.RuleSource ruleSource9 = SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WOODED_BADLANDS), SurfaceRules.ifTrue(conditionSource, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource14, COARSE_DIRT), SurfaceRules.ifTrue(conditionSource15, COARSE_DIRT), SurfaceRules.ifTrue(conditionSource16, COARSE_DIRT), ruleSource))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.SWAMP), SurfaceRules.ifTrue(conditionSource5, SurfaceRules.ifTrue(SurfaceRules.not(conditionSource6), SurfaceRules.ifTrue(SurfaceRules.noiseCondition(Noises.SWAMP, 0.0D), WATER)))))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.BADLANDS, Biomes.ERODED_BADLANDS, Biomes.WOODED_BADLANDS), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource2, ORANGE_TERRACOTTA), SurfaceRules.ifTrue(conditionSource4, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource14, TERRACOTTA), SurfaceRules.ifTrue(conditionSource15, TERRACOTTA), SurfaceRules.ifTrue(conditionSource16, TERRACOTTA), SurfaceRules.bandlands())), SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_CEILING, RED_SANDSTONE), RED_SAND)), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource10), ORANGE_TERRACOTTA), SurfaceRules.ifTrue(conditionSource9, WHITE_TERRACOTTA), ruleSource3)), SurfaceRules.ifTrue(conditionSource3, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource6, SurfaceRules.ifTrue(SurfaceRules.not(conditionSource4), ORANGE_TERRACOTTA)), SurfaceRules.bandlands())), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.ifTrue(conditionSource9, WHITE_TERRACOTTA)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource11, SurfaceRules.ifTrue(conditionSource10, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource8, AIR), SurfaceRules.ifTrue(SurfaceRules.temperature(), ICE), WATER))), ruleSource8))), SurfaceRules.ifTrue(conditionSource9, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource11, SurfaceRules.ifTrue(conditionSource10, WATER))), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, ruleSource7), SurfaceRules.ifTrue(conditionSource13, SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(0, true, true, CaveSurface.FLOOR), SANDSTONE)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.FROZEN_PEAKS, Biomes.JAGGED_PEAKS), STONE), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN), ruleSource2), ruleSource3)));
         Builder<SurfaceRules.RuleSource> builder = ImmutableList.builder();
         if (bedrockRoof) {
-            builder.add(SurfaceRules.ifTrue(SurfaceRules.not(SurfaceRules.verticalGradient("bedrock_roof", VerticalAnchor.belowTop(5), VerticalAnchor.top())), BEDROCK));
+            builder.add(SurfaceRules.ifTrue(SurfaceRules.not(new PaperBedrockConditionSource("bedrock_roof", VerticalAnchor.belowTop(5), VerticalAnchor.top(), true)), BEDROCK)); // Paper
         }
 
         if (bedrockFloor) {
-            builder.add(SurfaceRules.ifTrue(SurfaceRules.verticalGradient("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5)), BEDROCK));
+            builder.add(SurfaceRules.ifTrue(new PaperBedrockConditionSource("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5), false), BEDROCK)); // Paper
         }
 
         SurfaceRules.RuleSource ruleSource10 = SurfaceRules.ifTrue(SurfaceRules.abovePreliminarySurface(), ruleSource9);
@@ -111,7 +155,7 @@ public class SurfaceRuleData {
         SurfaceRules.ConditionSource conditionSource11 = SurfaceRules.noiseCondition(Noises.NETHER_WART, 1.17D);
         SurfaceRules.ConditionSource conditionSource12 = SurfaceRules.noiseCondition(Noises.NETHER_STATE_SELECTOR, 0.0D);
         SurfaceRules.RuleSource ruleSource = SurfaceRules.ifTrue(conditionSource9, SurfaceRules.ifTrue(conditionSource3, SurfaceRules.ifTrue(conditionSource4, GRAVEL)));
-        return SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.verticalGradient("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5)), BEDROCK), SurfaceRules.ifTrue(SurfaceRules.not(SurfaceRules.verticalGradient("bedrock_roof", VerticalAnchor.belowTop(5), VerticalAnchor.top())), BEDROCK), SurfaceRules.ifTrue(conditionSource5, NETHERRACK), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.BASALT_DELTAS), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.UNDER_CEILING, BASALT), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.sequence(ruleSource, SurfaceRules.ifTrue(conditionSource12, BASALT), BLACKSTONE)))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.SOUL_SAND_VALLEY), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.UNDER_CEILING, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource12, SOUL_SAND), SOUL_SOIL)), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.sequence(ruleSource, SurfaceRules.ifTrue(conditionSource12, SOUL_SAND), SOUL_SOIL)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.not(conditionSource2), SurfaceRules.ifTrue(conditionSource6, LAVA)), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WARPED_FOREST), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource10), SurfaceRules.ifTrue(conditionSource, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource11, WARPED_WART_BLOCK), WARPED_NYLIUM)))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.CRIMSON_FOREST), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource10), SurfaceRules.ifTrue(conditionSource, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource11, NETHER_WART_BLOCK), CRIMSON_NYLIUM)))))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.NETHER_WASTES), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.not(conditionSource6), SurfaceRules.ifTrue(conditionSource3, SurfaceRules.ifTrue(conditionSource4, SOUL_SAND))), NETHERRACK))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource, SurfaceRules.ifTrue(conditionSource4, SurfaceRules.ifTrue(conditionSource8, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource2, GRAVEL), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource6), GRAVEL)))))))), NETHERRACK);
+        return SurfaceRules.sequence(SurfaceRules.ifTrue(new PaperBedrockConditionSource("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5), false), BEDROCK), SurfaceRules.ifTrue(SurfaceRules.not(new PaperBedrockConditionSource("bedrock_roof", VerticalAnchor.belowTop(5), VerticalAnchor.top(), true)), BEDROCK), SurfaceRules.ifTrue(conditionSource5, NETHERRACK), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.BASALT_DELTAS), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.UNDER_CEILING, BASALT), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.sequence(ruleSource, SurfaceRules.ifTrue(conditionSource12, BASALT), BLACKSTONE)))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.SOUL_SAND_VALLEY), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.UNDER_CEILING, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource12, SOUL_SAND), SOUL_SOIL)), SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.sequence(ruleSource, SurfaceRules.ifTrue(conditionSource12, SOUL_SAND), SOUL_SOIL)))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.not(conditionSource2), SurfaceRules.ifTrue(conditionSource6, LAVA)), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.WARPED_FOREST), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource10), SurfaceRules.ifTrue(conditionSource, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource11, WARPED_WART_BLOCK), WARPED_NYLIUM)))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.CRIMSON_FOREST), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource10), SurfaceRules.ifTrue(conditionSource, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource11, NETHER_WART_BLOCK), CRIMSON_NYLIUM)))))), SurfaceRules.ifTrue(SurfaceRules.isBiome(Biomes.NETHER_WASTES), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SurfaceRules.ifTrue(conditionSource7, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.not(conditionSource6), SurfaceRules.ifTrue(conditionSource3, SurfaceRules.ifTrue(conditionSource4, SOUL_SAND))), NETHERRACK))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(conditionSource, SurfaceRules.ifTrue(conditionSource4, SurfaceRules.ifTrue(conditionSource8, SurfaceRules.sequence(SurfaceRules.ifTrue(conditionSource2, GRAVEL), SurfaceRules.ifTrue(SurfaceRules.not(conditionSource6), GRAVEL)))))))), NETHERRACK);
     }
 
     public static SurfaceRules.RuleSource end() {
diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
index 74ab13e89ee4a8f8c367706d86382f08e62520b3..09d814317443a86210245ab3a7902f2078f08131 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -231,7 +231,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
     @Override
     public void buildSurface(WorldGenRegion region, StructureFeatureManager structures, ChunkAccess chunk) {
         if (!SharedConstants.debugVoidTerrain(chunk.getPos())) {
-            WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, region);
+            WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, region, structures.getWorld()); // Paper
             NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get();
             NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk(this.sampler, () -> {
                 return new Beardifier(structures, chunk);
@@ -253,7 +253,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
             return new Beardifier(structureAccessor, chunk);
         }, (NoiseGeneratorSettings) this.settings.get(), this.globalFluidPicker, Blender.of(chunkRegion));
         Aquifer aquifer = noisechunk.aquifer();
-        CarvingContext carvingcontext = new CarvingContext(this, chunkRegion.registryAccess(), chunk.getHeightAccessorForGeneration(), noisechunk);
+        CarvingContext carvingcontext = new CarvingContext(this, chunkRegion.registryAccess(), chunk.getHeightAccessorForGeneration(), noisechunk, structureAccessor.getWorld()); // Paper
         CarvingMask carvingmask = ((ProtoChunk) chunk).getOrCreateCarvingMask(generationStep);
 
         for (int j = -8; j <= 8; ++j) {
diff --git a/src/main/java/net/minecraft/world/level/levelgen/WorldGenerationContext.java b/src/main/java/net/minecraft/world/level/levelgen/WorldGenerationContext.java
index b99283c31193e2110f6e3f39c23dbfc2442bab2b..eed55a3f95d30bcd4184b8dfd597af7da26281a2 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/WorldGenerationContext.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/WorldGenerationContext.java
@@ -6,10 +6,13 @@ import net.minecraft.world.level.chunk.ChunkGenerator;
 public class WorldGenerationContext {
     private final int minY;
     private final int height;
+    private final net.minecraft.world.level.Level level; // Paper
 
-    public WorldGenerationContext(ChunkGenerator generator, LevelHeightAccessor world) {
+    public WorldGenerationContext(ChunkGenerator generator, LevelHeightAccessor world) { this(generator, world, null); } // Paper
+    public WorldGenerationContext(ChunkGenerator generator, LevelHeightAccessor world, @org.jetbrains.annotations.Nullable net.minecraft.world.level.Level level) { // Paper
         this.minY = Math.max(world.getMinBuildHeight(), generator.getMinY());
         this.height = Math.min(world.getHeight(), generator.getGenDepth());
+        this.level = level; // Paper
     }
 
     public int getMinGenY() {
@@ -19,4 +22,13 @@ public class WorldGenerationContext {
     public int getGenDepth() {
         return this.height;
     }
+
+    // Paper start
+    public net.minecraft.world.level.Level getWorld() {
+        if (this.level == null) {
+            throw new NullPointerException("WorldGenerationContext was initialized without a Level, but WorldGenerationContext#getWorld was called");
+        }
+        return this.level;
+    }
+    // Paper end
 }
diff --git a/src/main/java/net/minecraft/world/level/levelgen/carver/CarvingContext.java b/src/main/java/net/minecraft/world/level/levelgen/carver/CarvingContext.java
index 0709cdae1be12a64b7105b50b7593b186797ca5b..bacc7a8de19f5938daf79f1829780efb6c2fcce4 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/carver/CarvingContext.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/carver/CarvingContext.java
@@ -17,8 +17,8 @@ public class CarvingContext extends WorldGenerationContext {
     private final RegistryAccess registryAccess;
     private final NoiseChunk noiseChunk;
 
-    public CarvingContext(NoiseBasedChunkGenerator chunkGenerator, RegistryAccess registryManager, LevelHeightAccessor heightLimitView, NoiseChunk chunkNoiseSampler) {
-        super(chunkGenerator, heightLimitView);
+    public CarvingContext(NoiseBasedChunkGenerator chunkGenerator, RegistryAccess registryManager, LevelHeightAccessor heightLimitView, NoiseChunk chunkNoiseSampler, @org.jetbrains.annotations.Nullable net.minecraft.world.level.Level level) { // Paper
+        super(chunkGenerator, heightLimitView, level); // Paper
         this.generator = chunkGenerator;
         this.registryAccess = registryManager;
         this.noiseChunk = chunkNoiseSampler;
diff --git a/src/main/java/net/minecraft/world/level/levelgen/placement/PlacementContext.java b/src/main/java/net/minecraft/world/level/levelgen/placement/PlacementContext.java
index 640c2683c842655bbaee8f293f1c2613ef44844e..53d818b0cc602f827d0b907e293515f6810c6792 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/placement/PlacementContext.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/placement/PlacementContext.java
@@ -18,7 +18,7 @@ public class PlacementContext extends WorldGenerationContext {
     private final Optional<PlacedFeature> topFeature;
 
     public PlacementContext(WorldGenLevel world, ChunkGenerator generator, Optional<PlacedFeature> placedFeature) {
-        super(generator, world);
+        super(generator, world, world.getLevel()); // Paper
         this.level = world;
         this.generator = generator;
         this.topFeature = placedFeature;
