aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0325-Flat-bedrock-generator-settings.patch
blob: 2bf8b308aab395b8e7203f1de2d4ef24b0eaf12d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
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

== AT ==
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 randomState
public net.minecraft.world.level.levelgen.SurfaceRules$LazyYCondition
public net.minecraft.world.level.levelgen.SurfaceRules$LazyCondition
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;

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

diff --git a/src/main/java/io/papermc/paper/world/worldgen/OptionallyFlatBedrockConditionSource.java b/src/main/java/io/papermc/paper/world/worldgen/OptionallyFlatBedrockConditionSource.java
new file mode 100644
index 0000000000000000000000000000000000000000..02d98ec591b676acf64460d14d608860d32a362a
--- /dev/null
+++ b/src/main/java/io/papermc/paper/world/worldgen/OptionallyFlatBedrockConditionSource.java
@@ -0,0 +1,76 @@
+package io.papermc.paper.world.worldgen;
+
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
+import net.minecraft.core.Registry;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.core.registries.Registries;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.util.KeyDispatchDataCodec;
+import net.minecraft.util.Mth;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.level.levelgen.PositionalRandomFactory;
+import net.minecraft.world.level.levelgen.SurfaceRules;
+import net.minecraft.world.level.levelgen.VerticalAnchor;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+// Modelled off of SurfaceRules$VerticalGradientConditionSource
+@DefaultQualifier(NonNull.class)
+public record OptionallyFlatBedrockConditionSource(ResourceLocation randomName, VerticalAnchor trueAtAndBelow, VerticalAnchor falseAtAndAbove, boolean isRoof) implements SurfaceRules.ConditionSource {
+
+    private static final ResourceKey<Codec<? extends SurfaceRules.ConditionSource>> CODEC_RESOURCE_KEY = ResourceKey.create(Registries.MATERIAL_CONDITION, new ResourceLocation(ResourceLocation.PAPER_NAMESPACE, "optionally_flat_bedrock_condition_source"));
+    private static final KeyDispatchDataCodec<OptionallyFlatBedrockConditionSource> CODEC = KeyDispatchDataCodec.of(RecordCodecBuilder.mapCodec((instance) -> {
+        return instance.group(
+            ResourceLocation.CODEC.fieldOf("random_name").forGetter(OptionallyFlatBedrockConditionSource::randomName),
+            VerticalAnchor.CODEC.fieldOf("true_at_and_below").forGetter(OptionallyFlatBedrockConditionSource::trueAtAndBelow),
+            VerticalAnchor.CODEC.fieldOf("false_at_and_above").forGetter(OptionallyFlatBedrockConditionSource::falseAtAndAbove),
+            Codec.BOOL.fieldOf("is_roof").forGetter(OptionallyFlatBedrockConditionSource::isRoof)
+        ).apply(instance, OptionallyFlatBedrockConditionSource::new);
+    }));
+
+    public static void bootstrap() {
+        Registry.register(BuiltInRegistries.MATERIAL_CONDITION, CODEC_RESOURCE_KEY, CODEC.codec());
+    }
+
+    @Override
+    public KeyDispatchDataCodec<? extends SurfaceRules.ConditionSource> codec() {
+        return CODEC;
+    }
+
+    @Override
+    public SurfaceRules.Condition apply(final SurfaceRules.Context context) {
+        boolean hasFlatBedrock = context.context.getWorld().paperConfig().environment.generateFlatBedrock;
+        int tempTrueAtAndBelowY = this.trueAtAndBelow().resolveY(context.context);
+        int tempFalseAtAndAboveY = this.falseAtAndAbove().resolveY(context.context);
+
+        int flatYLevel = this.isRoof ? Math.max(tempFalseAtAndAboveY, tempTrueAtAndBelowY) - 1 : Math.min(tempFalseAtAndAboveY, tempTrueAtAndBelowY);
+        final int trueAtAndBelowY = hasFlatBedrock ? flatYLevel : tempTrueAtAndBelowY;
+        final int falseAtAndAboveY = hasFlatBedrock ? flatYLevel : tempFalseAtAndAboveY;
+
+        final PositionalRandomFactory positionalRandomFactory = context.randomState.getOrCreateRandomFactory(this.randomName());
+
+        class VerticalGradientCondition extends SurfaceRules.LazyYCondition {
+            VerticalGradientCondition(SurfaceRules.Context context) {
+                super(context);
+            }
+
+            @Override
+            protected boolean compute() {
+                int blockY = this.context.blockY;
+                if (blockY <= trueAtAndBelowY) {
+                    return true;
+                } else if (blockY >= falseAtAndAboveY) {
+                    return false;
+                } else {
+                    double d = Mth.map(blockY, trueAtAndBelowY, falseAtAndAboveY, 1.0D, 0.0D);
+                    RandomSource randomSource = positionalRandomFactory.at(this.context.blockX, blockY, this.context.blockZ);
+                    return (double)randomSource.nextFloat() < d;
+                }
+            }
+        }
+
+        return new VerticalGradientCondition(context);
+    }
+}
diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java
index c887d34171f89c731d76c4ca92c70be2b1edc1e6..5816998cde8504d58732e63eb2179a5d828f35bb 100644
--- a/src/main/java/net/minecraft/server/Bootstrap.java
+++ b/src/main/java/net/minecraft/server/Bootstrap.java
@@ -78,6 +78,7 @@ public class Bootstrap {
                     CauldronInteraction.bootStrap();
                     // Paper start
                     BuiltInRegistries.bootStrap(() -> {
+                        io.papermc.paper.world.worldgen.OptionallyFlatBedrockConditionSource.bootstrap(); // Paper - optional flat bedrock
                         io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping
                     });
                     // Paper 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 902156477bdfc9917105f1229f760c26e5af302a..58609a0911c4e32b6f80f050cd3d23f70ad75b1b 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -207,7 +207,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
     @Override
     public void buildSurface(WorldGenRegion region, StructureManager structures, RandomState noiseConfig, ChunkAccess chunk) {
         if (!SharedConstants.debugVoidTerrain(chunk.getPos())) {
-            WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, region);
+            WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, region, region.getMinecraftWorld()); // Paper
 
             this.buildSurface(chunk, worldgenerationcontext, noiseConfig, structures, region.getBiomeManager(), region.registryAccess().registryOrThrow(Registries.BIOME), Blender.of(region));
         }
@@ -235,7 +235,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
             return this.createNoiseChunk(ichunkaccess1, structureAccessor, Blender.of(chunkRegion), noiseConfig);
         });
         Aquifer aquifer = noisechunk.aquifer();
-        CarvingContext carvingcontext = new CarvingContext(this, chunkRegion.registryAccess(), chunk.getHeightAccessorForGeneration(), noisechunk, noiseConfig, ((NoiseGeneratorSettings) this.settings.value()).surfaceRule());
+        CarvingContext carvingcontext = new CarvingContext(this, chunkRegion.registryAccess(), chunk.getHeightAccessorForGeneration(), noisechunk, noiseConfig, ((NoiseGeneratorSettings) this.settings.value()).surfaceRule(), chunkRegion.getMinecraftWorld()); // Paper
         CarvingMask carvingmask = ((ProtoChunk) chunk).getOrCreateCarvingMask(carverStep);
 
         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..1c9d9ecdafb2bd04348045ba0404da052dcd6437 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 @javax.annotation.Nullable 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 a745458ea3581ea91a68c863e3fd0a0292d73a61..f84ee8afe95f912a972e37fbae7a06ecdd3aba06 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
@@ -21,8 +21,8 @@ public class CarvingContext extends WorldGenerationContext {
     private final RandomState randomState;
     private final SurfaceRules.RuleSource surfaceRule;
 
-    public CarvingContext(NoiseBasedChunkGenerator noiseChunkGenerator, RegistryAccess registryManager, LevelHeightAccessor heightLimitView, NoiseChunk chunkNoiseSampler, RandomState noiseConfig, SurfaceRules.RuleSource materialRule) {
-        super(noiseChunkGenerator, heightLimitView);
+    public CarvingContext(NoiseBasedChunkGenerator noiseChunkGenerator, RegistryAccess registryManager, LevelHeightAccessor heightLimitView, NoiseChunk chunkNoiseSampler, RandomState noiseConfig, SurfaceRules.RuleSource materialRule, @javax.annotation.Nullable net.minecraft.world.level.Level level) { // Paper
+        super(noiseChunkGenerator, heightLimitView, level); // Paper
         this.registryAccess = registryManager;
         this.noiseChunk = chunkNoiseSampler;
         this.randomState = noiseConfig;
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;
diff --git a/src/main/resources/data/minecraft/worldgen/noise_settings/amplified.json b/src/main/resources/data/minecraft/worldgen/noise_settings/amplified.json
index 3f61ea695aa6a91a0cacf1fa8dc0a9bdc6fa36e6..02d32bbdbc795db271205bef95e6987ac34b0136 100644
--- a/src/main/resources/data/minecraft/worldgen/noise_settings/amplified.json
+++ b/src/main/resources/data/minecraft/worldgen/noise_settings/amplified.json
@@ -389,7 +389,8 @@
       {
         "type": "minecraft:condition",
         "if_true": {
-          "type": "minecraft:vertical_gradient",
+          "type": "paper:optionally_flat_bedrock_condition_source",
+          "is_roof": false,
           "false_at_and_above": {
             "above_bottom": 5
           },
diff --git a/src/main/resources/data/minecraft/worldgen/noise_settings/caves.json b/src/main/resources/data/minecraft/worldgen/noise_settings/caves.json
index 1fe9ce904cba21ff4e6efb948a0bc274a22bcb0b..2e8c1aad10a2b0adbdee4180cfc1902984b6565b 100644
--- a/src/main/resources/data/minecraft/worldgen/noise_settings/caves.json
+++ b/src/main/resources/data/minecraft/worldgen/noise_settings/caves.json
@@ -110,7 +110,8 @@
         "if_true": {
           "type": "minecraft:not",
           "invert": {
-            "type": "minecraft:vertical_gradient",
+            "type": "paper:optionally_flat_bedrock_condition_source",
+            "is_roof": true,
             "false_at_and_above": {
               "below_top": 0
             },
@@ -130,7 +131,8 @@
       {
         "type": "minecraft:condition",
         "if_true": {
-          "type": "minecraft:vertical_gradient",
+          "type": "paper:optionally_flat_bedrock_condition_source",
+          "is_roof": false,
           "false_at_and_above": {
             "above_bottom": 5
           },
diff --git a/src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json b/src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json
index f4c34de998d78a80bc026d8e0d423c9bed9bbf8a..fd5bd5474b8f931f2e04706997e71cd5145a5a82 100644
--- a/src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json
+++ b/src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json
@@ -389,7 +389,8 @@
       {
         "type": "minecraft:condition",
         "if_true": {
-          "type": "minecraft:vertical_gradient",
+          "type": "paper:optionally_flat_bedrock_condition_source",
+          "is_roof": false,
           "false_at_and_above": {
             "above_bottom": 5
           },
diff --git a/src/main/resources/data/minecraft/worldgen/noise_settings/nether.json b/src/main/resources/data/minecraft/worldgen/noise_settings/nether.json
index 6219d25fcdbc761debc1d1e357757d1b977dc0b0..1657179b8c3f7e549e3b8774ecb75f292ae79c38 100644
--- a/src/main/resources/data/minecraft/worldgen/noise_settings/nether.json
+++ b/src/main/resources/data/minecraft/worldgen/noise_settings/nether.json
@@ -108,7 +108,8 @@
       {
         "type": "minecraft:condition",
         "if_true": {
-          "type": "minecraft:vertical_gradient",
+          "type": "paper:optionally_flat_bedrock_condition_source",
+          "is_roof": false,
           "false_at_and_above": {
             "above_bottom": 5
           },
@@ -129,7 +130,8 @@
         "if_true": {
           "type": "minecraft:not",
           "invert": {
-            "type": "minecraft:vertical_gradient",
+            "type": "paper:optionally_flat_bedrock_condition_source",
+            "is_roof": true,
             "false_at_and_above": {
               "below_top": 0
             },
diff --git a/src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json b/src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json
index da3bda6167859f4ddf7d76ec2053f40b2139c13e..70beb7665a43a06b4afcb3c77aa77f923cb444cb 100644
--- a/src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json
+++ b/src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json
@@ -389,7 +389,8 @@
       {
         "type": "minecraft:condition",
         "if_true": {
-          "type": "minecraft:vertical_gradient",
+          "type": "paper:optionally_flat_bedrock_condition_source",
+          "is_roof": false,
           "false_at_and_above": {
             "above_bottom": 5
           },