aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0680-Implement-regenerateChunk.patch
blob: c6a6c8eb34757c084016b160a08a2deb51e54763 (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
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 43b3af7bba4551d98c7ffb53fbee9413ed5b8dd3..e31794510cb204fa1360803050d25d0e226785e2 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<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);
+                }
+            }
+
+            final java.util.concurrent.CompletableFuture<ChunkAccess> 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<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));
+            }
         }
 
-        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