From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Mon, 31 Jan 2022 11:21:50 +0100 Subject: [PATCH] Implement regenerateChunk Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com> diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 8d41492cd6305331deca3748eb24d689f23e280b..365a23218c57f9685c79b520d7721e5a49b7771c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -151,6 +151,7 @@ import org.jetbrains.annotations.Nullable; public class CraftWorld extends CraftRegionAccessor implements World { public static final int CUSTOM_DIMENSION_OFFSET = 10; private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + private static final ChunkStatus[] REGEN_CHUNK_STATUSES = {ChunkStatus.BIOMES, ChunkStatus.NOISE, ChunkStatus.SURFACE, ChunkStatus.CARVERS, ChunkStatus.FEATURES, ChunkStatus.INITIALIZE_LIGHT}; // Paper - implement regenerate chunk method private final ServerLevel world; private WorldBorder worldBorder; @@ -421,27 +422,70 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean regenerateChunk(int x, int z) { org.spigotmc.AsyncCatcher.catchOp("chunk regenerate"); // Spigot - throw new UnsupportedOperationException("Not supported in this Minecraft version! Unless you can fix it, this is not a bug :)"); - /* - if (!unloadChunk0(x, z, false)) { - return false; + // Paper start - implement regenerateChunk method + final ServerLevel serverLevel = this.world; + final net.minecraft.server.level.ServerChunkCache serverChunkCache = serverLevel.getChunkSource(); + final ChunkPos chunkPos = new ChunkPos(x, z); + final net.minecraft.world.level.chunk.LevelChunk levelChunk = serverChunkCache.getChunk(chunkPos.x, chunkPos.z, true); + for (final BlockPos blockPos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), serverLevel.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), serverLevel.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ())) { + levelChunk.removeBlockEntity(blockPos); + serverLevel.setBlock(blockPos, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), 16); + } + + for (final ChunkStatus chunkStatus : REGEN_CHUNK_STATUSES) { + final List list = new ArrayList<>(); + final int range = Math.max(1, chunkStatus.getRange()); + for (int chunkX = chunkPos.z - range; chunkX <= chunkPos.z + range; chunkX++) { + for (int chunkZ = chunkPos.x - range; chunkZ <= chunkPos.x + range; chunkZ++) { + ChunkAccess chunkAccess = serverChunkCache.getChunk(chunkZ, chunkX, chunkStatus.getParent(), true); + if (chunkAccess instanceof ImposterProtoChunk accessProtoChunk) { + chunkAccess = new ImposterProtoChunk(accessProtoChunk.getWrapped(), true); + } else if (chunkAccess instanceof net.minecraft.world.level.chunk.LevelChunk accessLevelChunk) { + chunkAccess = new ImposterProtoChunk(accessLevelChunk, true); + } + list.add(chunkAccess); + } + } + + final java.util.concurrent.CompletableFuture future = chunkStatus.generate( + new net.minecraft.world.level.chunk.status.WorldGenContext( + serverLevel, + serverChunkCache.getGenerator(), + serverLevel.getStructureManager(), + serverChunkCache.getLightEngine() + ), + Runnable::run, + chunk -> { + throw new UnsupportedOperationException("Not creating full chunks here"); + }, + list + ); + serverChunkCache.mainThreadProcessor.managedBlock(future::isDone); + if (chunkStatus == ChunkStatus.NOISE) { + net.minecraft.world.level.levelgen.Heightmap.primeHeightmaps(future.join(), ChunkStatus.POST_FEATURES); + } } - final long chunkKey = ChunkCoordIntPair.pair(x, z); - world.getChunkProvider().unloadQueue.remove(chunkKey); + for (final BlockPos blockPos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), serverLevel.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), serverLevel.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ())) { + serverChunkCache.blockChanged(blockPos); + } - net.minecraft.server.Chunk chunk = world.getChunkProvider().generateChunk(x, z); - PlayerChunk playerChunk = world.getPlayerChunkMap().getChunk(x, z); - if (playerChunk != null) { - playerChunk.chunk = chunk; + final Set chunksToRelight = new HashSet<>(9); + for (int chunkX = chunkPos.x - 1; chunkX <= chunkPos.x + 1 ; chunkX++) { + for (int chunkZ = chunkPos.z - 1; chunkZ <= chunkPos.z + 1 ; chunkZ++) { + chunksToRelight.add(new ChunkPos(chunkX, chunkZ)); + } } - if (chunk != null) { - refreshChunk(x, z); + for (final ChunkPos pos : chunksToRelight) { + final ChunkAccess chunk = serverChunkCache.getChunk(pos.x, pos.z, false); + if (chunk != null) { + serverChunkCache.getLightEngine().lightChunk(chunk, false); + } } - return chunk != null; - */ + return true; + // Paper end - implement regenerate chunk method } @Override