diff --git a/build-data/paper.at b/build-data/paper.at
index 0b90f95521..5394004025 100644
--- a/build-data/paper.at
+++ b/build-data/paper.at
@@ -272,5 +272,18 @@ public net.minecraft.world.level.chunk.LevelChunkSection states
 # Player.setPlayerProfile API
 public-f net.minecraft.world.entity.player.Player gameProfile
 
+# Generator Settings
+public net.minecraft.world.level.levelgen.SurfaceRules$Condition
+public net.minecraft.world.level.levelgen.SurfaceRules$Context
+public net.minecraft.world.level.levelgen.SurfaceRules$Context blockX
+public net.minecraft.world.level.levelgen.SurfaceRules$Context blockY
+public net.minecraft.world.level.levelgen.SurfaceRules$Context blockZ
+public net.minecraft.world.level.levelgen.SurfaceRules$Context context
+public net.minecraft.world.level.levelgen.SurfaceRules$Context system
+public net.minecraft.world.level.levelgen.SurfaceRules$LazyYCondition
+public net.minecraft.world.level.levelgen.SurfaceRules$VerticalGradientConditionSource
+public net.minecraft.world.level.levelgen.SurfaceRules$SurfaceRule
+public net.minecraft.world.level.levelgen.SurfaceSystem getOrCreateRandomFactory(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/world/level/levelgen/PositionalRandomFactory;
+
 # Fix removing recipes
 public net.minecraft.world.item.crafting.RecipeManager byName
diff --git a/patches/server/Flat-bedrock-generator-settings.patch b/patches/server/Flat-bedrock-generator-settings.patch
new file mode 100644
index 0000000000..f2ba1c410c
--- /dev/null
+++ b/patches/server/Flat-bedrock-generator-settings.patch
@@ -0,0 +1,183 @@
+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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java
++++ b/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java
+@@ -0,0 +0,0 @@ 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);
+@@ -0,0 +0,0 @@ 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);
+@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+@@ -0,0 +0,0 @@ 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);
+@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/level/levelgen/WorldGenerationContext.java
++++ b/src/main/java/net/minecraft/world/level/levelgen/WorldGenerationContext.java
+@@ -0,0 +0,0 @@ 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() {
+@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
+@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
+@@ -0,0 +0,0 @@ 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;
diff --git a/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch
index ff089066b2..b5f9c448d5 100644
--- a/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch
+++ b/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch
@@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
 +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
 @@ -0,0 +0,0 @@ public class PaperWorldConfig {
-     private void pillagerSettings() {
-         disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols);
+     private void generatorSettings() {
+         generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", this.generateFlatBedrock);
      }
 +
 +    public boolean entitiesTargetWithFollowRange = false;
diff --git a/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch
index 5094e0d197..64a1a83ca6 100644
--- a/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch
+++ b/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch
@@ -31,10 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay);
      }
  
-+
-     public boolean entitiesTargetWithFollowRange = false;
-     private void entitiesTargetWithFollowRange() {
-         entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange);
+     public boolean generateFlatBedrock = false;
 diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java