97 lines
		
	
	
	
		
			5.5 KiB
			
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
	
		
			5.5 KiB
			
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
						|
From: Nassim Jahnke <nassim@njahnke.dev>
 | 
						|
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
						|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
 | 
						|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
 | 
						|
@@ -0,0 +0,0 @@ import org.jetbrains.annotations.NotNull;
 | 
						|
 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;
 | 
						|
@@ -0,0 +0,0 @@ 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;
 | 
						|
-        }
 | 
						|
-
 | 
						|
-        final long chunkKey = ChunkCoordIntPair.pair(x, z);
 | 
						|
-        world.getChunkProvider().unloadQueue.remove(chunkKey);
 | 
						|
+        // 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<ChunkAccess> 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);
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
 
 | 
						|
-        net.minecraft.server.Chunk chunk = world.getChunkProvider().generateChunk(x, z);
 | 
						|
-        PlayerChunk playerChunk = world.getPlayerChunkMap().getChunk(x, z);
 | 
						|
-        if (playerChunk != null) {
 | 
						|
-            playerChunk.chunk = chunk;
 | 
						|
+            final java.util.concurrent.CompletableFuture<com.mojang.datafixers.util.Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = chunkStatus.generate(
 | 
						|
+                Runnable::run,
 | 
						|
+                serverLevel,
 | 
						|
+                serverChunkCache.getGenerator(),
 | 
						|
+                serverLevel.getStructureManager(),
 | 
						|
+                serverChunkCache.getLightEngine(),
 | 
						|
+                chunk -> {
 | 
						|
+                    throw new UnsupportedOperationException("Not creating full chunks here");
 | 
						|
+                },
 | 
						|
+                list
 | 
						|
+            );
 | 
						|
+            serverChunkCache.mainThreadProcessor.managedBlock(future::isDone);
 | 
						|
+            if (chunkStatus == ChunkStatus.NOISE) {
 | 
						|
+                future.join().left().ifPresent(chunk -> net.minecraft.world.level.levelgen.Heightmap.primeHeightmaps(chunk, ChunkStatus.POST_FEATURES));
 | 
						|
+            }
 | 
						|
         }
 | 
						|
 
 | 
						|
-        if (chunk != null) {
 | 
						|
-            refreshChunk(x, z);
 | 
						|
+        for (final BlockPos blockPos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), serverLevel.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), serverLevel.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ())) {
 | 
						|
+            serverChunkCache.blockChanged(blockPos);
 | 
						|
         }
 | 
						|
 
 | 
						|
-        return chunk != null;
 | 
						|
-        */
 | 
						|
+        final Set<ChunkPos> 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));
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+        serverChunkCache.getLightEngine().relight(chunksToRelight, pos -> {}, relit -> {});
 | 
						|
+        return true;
 | 
						|
+        // Paper end
 | 
						|
     }
 | 
						|
 
 | 
						|
     @Override
 |