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] Generator Settings


diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 4c177a383b277debe8a7c02a70d029d862e6b048..0c336a794d21d5084b9ea39308379b2ffb4a4330 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -416,5 +416,10 @@ public class PaperWorldConfig {
     private void disableRelativeProjectileVelocity() {
         disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false);
     }
+
+    public boolean generateFlatBedrock;
+    private void generatorSettings() {
+        generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false);
+    }
 }
 
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index c687f6b2b97fc32bd01add75d6327f0debbfb290..579568e90a220ea43ed83df38e6dc3613da850e4 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -676,7 +676,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
             }
 
             this.markPositionReplaceable(pos);
-            return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level));
+            return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level)); // Paper - add level
             // Paper start - Async chunk io
         };
         CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> ret = new CompletableFuture<>();
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 974ab04b08bbd3c27a394b37c1af112be5f28f43..c0075d226331f32e470dae5bf1ce8d79e8b263dc 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -29,6 +29,18 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess {
         return GameEventDispatcher.NOOP;
     }
 
+    // Paper start
+    default boolean generateFlatBedrock() {
+        if (this instanceof ProtoChunk) {
+            return ((ProtoChunk)this).level.paperConfig.generateFlatBedrock;
+        } else if (this instanceof LevelChunk) {
+            return ((LevelChunk)this).level.paperConfig.generateFlatBedrock;
+        } else {
+            return false;
+        }
+    }
+    // Paper end
+
     BlockState getType(final int x, final int y, final int z); // Paper
     @Nullable
     BlockState setBlockState(BlockPos pos, BlockState state, boolean moved);
diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
index 452b513e8b89d865a396066adaf4feb1140e1c62..8245c5834ec69beb8e3b95fb3900601009a9273f 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -25,7 +25,7 @@ public class ImposterProtoChunk extends ProtoChunk {
     private final LevelChunk wrapped;
 
     public ImposterProtoChunk(LevelChunk wrapped) {
-        super(wrapped.getPos(), UpgradeData.EMPTY, wrapped);
+        super(wrapped.getPos(), UpgradeData.EMPTY, wrapped, wrapped.level); // Paper - add level
         this.wrapped = wrapped;
     }
 
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
index da36e6d40ad3e8b7cdbe09ef911d1e5b8c28670f..245998e2cea32cf15ee2659639c647f449704ec0 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -63,16 +63,24 @@ public class ProtoChunk implements ChunkAccess {
     private long inhabitedTime;
     private final Map<GenerationStep.Carving, BitSet> carvingMasks = new Object2ObjectArrayMap<>();
     private volatile boolean isLightCorrect;
+    final net.minecraft.world.level.Level level; // Paper - Add level
 
-    public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) {
+    // Paper start - add level
+    @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); }
+    public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) {
+        // Paper end
         this(pos, upgradeData, (LevelChunkSection[])null, new ProtoTickList<>((block) -> {
             return block == null || block.defaultBlockState().isAir();
         }, pos, world), new ProtoTickList<>((fluid) -> {
             return fluid == null || fluid == Fluids.EMPTY;
-        }, pos, world), world);
+        }, pos, world), world, level); // Paper - add level
     }
 
-    public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList<Block> blockTickScheduler, ProtoTickList<Fluid> fluidTickScheduler, LevelHeightAccessor world) {
+    // Paper start - add level
+    @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList<Block> blockTickScheduler, ProtoTickList<Fluid> fluidTickScheduler, LevelHeightAccessor world) { this(pos, upgradeData, levelChunkSections, blockTickScheduler, fluidTickScheduler, world, null); }
+    public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList<Block> blockTickScheduler, ProtoTickList<Fluid> fluidTickScheduler, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) {
+        this.level = level;
+        // Paper end
         this.chunkPos = pos;
         this.upgradeData = upgradeData;
         this.blockTicks = blockTickScheduler;
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index 1c975b686c1e335d46e63ab12e0a97dd2dcaba13..34a026dbeafff07401187d22ef8fd537c17fc615 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -210,7 +210,7 @@ public class ChunkSerializer {
                 // CraftBukkit end
             });
         } else {
-            ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world);
+            ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level
 
             protochunk.setBiomes(biomestorage);
             object = protochunk;
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 a0a3cf7655eca5c2b181476b0842d9e8c19dbffd..db0abd275be2df7a4fdeb1d7179bff4d61bab052 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -270,8 +270,8 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
         int j = chunk.getPos().getMinBlockZ();
         NoiseGeneratorSettings noiseGeneratorSettings = this.settings.get();
         int k = noiseGeneratorSettings.noiseSettings().minY();
-        int l = k + noiseGeneratorSettings.getBedrockFloorPosition();
-        int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition();
+        int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); final int floorHeight = k; // Paper
+        int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); final int roofHeight = l; // Paper
         int n = 5;
         int o = chunk.getMinBuildHeight();
         int p = chunk.getMaxBuildHeight();
@@ -281,7 +281,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
             for(BlockPos blockPos : BlockPos.betweenClosed(i, 0, j, i + 15, 0, j + 15)) {
                 if (bl) {
                     for(int q = 0; q < 5; ++q) {
-                        if (q <= random.nextInt(5)) {
+                        if (q <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof
                             chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), m - q, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false);
                         }
                     }
@@ -289,7 +289,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
 
                 if (bl2) {
                     for(int r = 4; r >= 0; --r) {
-                        if (r <= random.nextInt(5)) {
+                        if (r <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor
                             chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), l + r, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false);
                         }
                     }
@@ -309,14 +309,14 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
         if (l <= 0) {
             return CompletableFuture.completedFuture(chunk);
         } else {
-            int m = chunk.getSectionIndex(l * this.cellHeight - 1 + i);
+            int mStart = chunk.getSectionIndex(l * this.cellHeight - 1 + i); // Paper - decompile fix
             int n = chunk.getSectionIndex(i);
             return CompletableFuture.supplyAsync(() -> {
                 Set<LevelChunkSection> set = Sets.newHashSet();
 
                 ChunkAccess var16;
                 try {
-                    for(int m = m; m >= n; --m) {
+                    for(int m = mStart; m >= n; --m) { // Paper - decompile fix
                         LevelChunkSection levelChunkSection = chunk.getOrCreateSection(m);
                         levelChunkSection.acquire();
                         set.add(levelChunkSection);