From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MiniDigger <admin@benndorf.dev>
Date: Wed, 29 Apr 2020 02:10:32 +0200
Subject: [PATCH] Allow delegation to vanilla chunk gen


diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 3af2e5d3bdbf82c142f5ea2629456329bda7666f..961a68252baabb0b7ccc9f7aa88dcb7516d0865f 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2353,6 +2353,90 @@ public final class CraftServer implements Server {
         return new OldCraftChunkData(world.getMinHeight(), world.getMaxHeight(), handle.registryAccess().registryOrThrow(Registries.BIOME), world); // Paper - Anti-Xray - Add parameters
     }
 
+    // Paper start
+    private static final List<net.minecraft.world.level.chunk.ChunkStatus> VANILLA_GEN_STATUSES = List.of(
+        net.minecraft.world.level.chunk.ChunkStatus.EMPTY,
+        net.minecraft.world.level.chunk.ChunkStatus.STRUCTURE_STARTS,
+        net.minecraft.world.level.chunk.ChunkStatus.STRUCTURE_REFERENCES,
+        net.minecraft.world.level.chunk.ChunkStatus.BIOMES,
+        net.minecraft.world.level.chunk.ChunkStatus.NOISE,
+        net.minecraft.world.level.chunk.ChunkStatus.SURFACE,
+        net.minecraft.world.level.chunk.ChunkStatus.CARVERS,
+        net.minecraft.world.level.chunk.ChunkStatus.LIQUID_CARVERS,
+        net.minecraft.world.level.chunk.ChunkStatus.FEATURES,
+        net.minecraft.world.level.chunk.ChunkStatus.LIGHT
+    );
+
+    @Override
+    @Deprecated(forRemoval = true)
+    public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) {
+        // do bunch of vanilla shit
+        final net.minecraft.server.level.ServerLevel serverLevel = ((CraftWorld) world).getHandle();
+        final net.minecraft.core.Registry<net.minecraft.world.level.biome.Biome> biomeRegistry = serverLevel.getServer().registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME);
+        final net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(
+            new net.minecraft.world.level.ChunkPos(x, z),
+            net.minecraft.world.level.chunk.UpgradeData.EMPTY,
+            serverLevel,
+            biomeRegistry,
+            null
+        );
+
+        final net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator;
+        if (serverLevel.chunkSource.getGenerator() instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator bukkit) {
+            chunkGenerator = bukkit.getDelegate();
+        } else {
+            chunkGenerator = serverLevel.chunkSource.getGenerator();
+        }
+
+        final net.minecraft.world.level.ChunkPos chunkPos = new net.minecraft.world.level.ChunkPos(x, z);
+        final net.minecraft.util.thread.ProcessorMailbox<Runnable> mailbox = net.minecraft.util.thread.ProcessorMailbox.create(
+            net.minecraft.Util.backgroundExecutor(),
+            "CraftServer#createVanillaChunkData(worldName='" + world.getName() + "', x='" + x + "', z='" + z + "')"
+        );
+        for (final net.minecraft.world.level.chunk.ChunkStatus chunkStatus : VANILLA_GEN_STATUSES) {
+            final List<net.minecraft.world.level.chunk.ChunkAccess> chunks = Lists.newArrayList();
+            final int statusRange = Math.max(1, chunkStatus.getRange());
+
+            for (int zz = chunkPos.z - statusRange; zz <= chunkPos.z + statusRange; ++zz) {
+                for (int xx = chunkPos.x - statusRange; xx <= chunkPos.x + statusRange; ++xx) {
+                    if (xx == chunkPos.x && zz == chunkPos.z) {
+                        chunks.add(protoChunk);
+                    } else {
+                        final net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> biomeHolder = serverLevel.registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME).getHolderOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
+                        final net.minecraft.world.level.chunk.ChunkAccess chunk = new net.minecraft.world.level.chunk.EmptyLevelChunk(serverLevel, new net.minecraft.world.level.ChunkPos(xx, zz), biomeHolder);
+                        chunks.add(chunk);
+                    }
+                }
+            }
+
+            chunkStatus.generate(
+                mailbox::tell,
+                serverLevel,
+                chunkGenerator,
+                serverLevel.getStructureManager(),
+                serverLevel.chunkSource.getLightEngine(),
+                chunk -> {
+                    throw new UnsupportedOperationException("Not creating full chunks here");
+                },
+                chunks,
+                true
+            ).thenAccept(either -> {
+                if (chunkStatus == net.minecraft.world.level.chunk.ChunkStatus.NOISE) {
+                    either.left().ifPresent(chunk -> net.minecraft.world.level.levelgen.Heightmap.primeHeightmaps(chunk, net.minecraft.world.level.chunk.ChunkStatus.POST_FEATURES));
+                }
+            }).join();
+        }
+
+        // get empty object
+        OldCraftChunkData data = (OldCraftChunkData) this.createChunkData(world);
+        // copy over generated sections
+        data.getLights().addAll(protoChunk.getLights().toList());
+        data.setRawChunkData(protoChunk.getSections());
+        // hooray!
+        return data;
+    }
+    // Paper end
+
     @Override
     public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) {
         return new CraftBossBar(title, color, style, flags);
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java
index 4a23d03757e1735b9ebb8c003adcc0374a7d672d..ce006e1d6c38e5b0bdb336c480fb9d291292f75c 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/OldCraftChunkData.java
@@ -23,7 +23,7 @@ import org.bukkit.material.MaterialData;
 public final class OldCraftChunkData implements ChunkGenerator.ChunkData {
     private final int minHeight;
     private final int maxHeight;
-    private final LevelChunkSection[] sections;
+    private LevelChunkSection[] sections; // Paper
     private final Registry<net.minecraft.world.level.biome.Biome> biomes;
     private Set<BlockPos> tiles;
     private final Set<BlockPos> lights = new HashSet<>();
@@ -194,7 +194,13 @@ public final class OldCraftChunkData implements ChunkGenerator.ChunkData {
         return this.tiles;
     }
 
-    Set<BlockPos> getLights() {
+    public Set<BlockPos> getLights() { // Paper
         return this.lights;
     }
+
+    // Paper start
+    public void setRawChunkData(LevelChunkSection[] sections) {
+        this.sections = sections;
+    }
+    // Paper end
 }
