aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0704-Implement-regenerateChunk.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0704-Implement-regenerateChunk.patch')
-rw-r--r--patches/server/0704-Implement-regenerateChunk.patch97
1 files changed, 97 insertions, 0 deletions
diff --git a/patches/server/0704-Implement-regenerateChunk.patch b/patches/server/0704-Implement-regenerateChunk.patch
new file mode 100644
index 0000000000..593c5cbe31
--- /dev/null
+++ b/patches/server/0704-Implement-regenerateChunk.patch
@@ -0,0 +1,97 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Nassim Jahnke <[email protected]>
+Date: Mon, 31 Jan 2022 11:21:50 +0100
+Subject: [PATCH] Implement regenerateChunk
+
+Co-authored-by: Jason Penilla <[email protected]>
+
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+index 6233e58820f12b6e0715a2f3c5ce448d24d864fc..967ee7a4fed61d229599349d05f7a506aa26a3de 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+@@ -144,6 +144,7 @@ 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;
+@@ -414,27 +415,61 @@ 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 - implement regenerate chunk method
+ }
+
+ @Override