aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch')
-rw-r--r--patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch122
1 files changed, 122 insertions, 0 deletions
diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch
new file mode 100644
index 0000000000..3e97a8baff
--- /dev/null
+++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch
@@ -0,0 +1,122 @@
+--- a/net/minecraft/server/level/ChunkHolder.java
++++ b/net/minecraft/server/level/ChunkHolder.java
+@@ -36,6 +36,10 @@
+ import net.minecraft.world.level.chunk.ProtoChunk;
+ import net.minecraft.world.level.lighting.LevelLightEngine;
+
++// CraftBukkit start
++import net.minecraft.server.MinecraftServer;
++// CraftBukkit end
++
+ public class ChunkHolder {
+
+ public static final Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> UNLOADED_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED);
+@@ -90,9 +94,23 @@
+ this.changedBlocksPerSection = new ShortSet[levelheightaccessor.getSectionsCount()];
+ }
+
+- public CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getFutureIfPresentUnchecked(ChunkStatus chunkstatus) {
+- CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = (CompletableFuture) this.futures.get(chunkstatus.getIndex());
++ // CraftBukkit start
++ public LevelChunk getFullChunkNow() {
++ // Note: We use the oldTicketLevel for isLoaded checks.
++ if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null;
++ return this.getFullChunkNowUnchecked();
++ }
+
++ public LevelChunk getFullChunkNowUnchecked() {
++ CompletableFuture<Either<ChunkAccess, ChunkHolder.Failure>> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL);
++ Either<ChunkAccess, ChunkHolder.Failure> either = (Either<ChunkAccess, ChunkHolder.Failure>) statusFuture.getNow(null);
++ return (either == null) ? null : (LevelChunk) either.left().orElse(null);
++ }
++ // CraftBukkit end
++
++ public CompletableFuture<Either<ChunkAccess, ChunkHolder.Failure>> getFutureIfPresentUnchecked(ChunkStatus chunkStatus) {
++ CompletableFuture<Either<ChunkAccess, ChunkHolder.Failure>> completablefuture = (CompletableFuture) this.futures.get(chunkStatus.getIndex());
++
+ return completablefuture == null ? ChunkHolder.UNLOADED_CHUNK_FUTURE : completablefuture;
+ }
+
+@@ -179,6 +197,7 @@
+ if (levelchunk != null) {
+ int i = this.levelHeightAccessor.getSectionIndex(blockpos.getY());
+
++ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
+ if (this.changedBlocksPerSection[i] == null) {
+ this.hasChangedSections = true;
+ this.changedBlocksPerSection[i] = new ShortOpenHashSet();
+@@ -256,9 +275,12 @@
+ LevelChunkSection levelchunksection = levelchunk.getSection(i);
+ ClientboundSectionBlocksUpdatePacket clientboundsectionblocksupdatepacket = new ClientboundSectionBlocksUpdatePacket(sectionpos, shortset, levelchunksection);
+
+- this.broadcast(list, clientboundsectionblocksupdatepacket);
+- clientboundsectionblocksupdatepacket.runUpdates((blockpos1, blockstate1) -> {
+- this.broadcastBlockEntityIfNeeded(list, level, blockpos1, blockstate1);
++ this.broadcast(list, packetplayoutmultiblockchange);
++ // CraftBukkit start
++ List finalList = list;
++ packetplayoutmultiblockchange.runUpdates((blockposition1, iblockdata1) -> {
++ this.broadcastBlockEntityIfNeeded(finalList, world, blockposition1, iblockdata1);
++ // CraftBukkit end
+ });
+ }
+ }
+@@ -411,7 +433,31 @@
+ boolean flag1 = ChunkLevel.isLoaded(this.ticketLevel);
+ FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel);
+ FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel);
++ // CraftBukkit start
++ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
++ if (fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && !fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) {
++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
++ LevelChunk chunk = (LevelChunk)either.left().orElse(null);
++ if (chunk != null) {
++ chunkMap.callbackExecutor.execute(() -> {
++ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick
++ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag.
++ // These actions may however happen deferred, so we manually set the needsSaving flag already here.
++ chunk.setUnsaved(true);
++ chunk.unloadCallback();
++ });
++ }
++ }).exceptionally((throwable) -> {
++ // ensure exceptions are printed, by default this is not the case
++ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + ChunkHolder.this.pos, throwable);
++ return null;
++ });
+
++ // Run callback right away if the future was already done
++ chunkMap.callbackExecutor.run();
++ }
++ // CraftBukkit end
++
+ if (flag) {
+ Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> either = Either.right(new ChunkHolder.ChunkLoadingFailure() {
+ @Override
+@@ -482,6 +527,26 @@
+
+ this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel);
+ this.oldTicketLevel = this.ticketLevel;
++ // CraftBukkit start
++ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins.
++ if (!fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) {
++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
++ LevelChunk chunk = (LevelChunk)either.left().orElse(null);
++ if (chunk != null) {
++ chunkMap.callbackExecutor.execute(() -> {
++ chunk.loadCallback();
++ });
++ }
++ }).exceptionally((throwable) -> {
++ // ensure exceptions are printed, by default this is not the case
++ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + ChunkHolder.this.pos, throwable);
++ return null;
++ });
++
++ // Run callback right away if the future was already done
++ chunkMap.callbackExecutor.run();
++ }
++ // CraftBukkit end
+ }
+
+ public boolean wasAccessibleSinceLastSave() {