From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MiniDigger 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 9d1a5979b59bbd1efe03d39b12fc726836637614..c5635cec189653b6a5559e99f48ca9149925e338 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -2363,6 +2363,88 @@ 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 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.FEATURES, + net.minecraft.world.level.chunk.ChunkStatus.INITIALIZE_LIGHT, + 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 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 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 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 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 + ).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.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 a9700b750f124b5367c91ac071ee5194e9f7f8d8..1a363ceeefbf69618e5f17f67b6f6a2660579ba5 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 biomes; private Set tiles; private final Set lights = new HashSet<>(); @@ -194,7 +194,13 @@ public final class OldCraftChunkData implements ChunkGenerator.ChunkData { return this.tiles; } - Set getLights() { + public Set getLights() { // Paper return this.lights; } + + // Paper start + public void setRawChunkData(LevelChunkSection[] sections) { + this.sections = sections; + } + // Paper end }