2021-03-15 23:00:00 +01:00
|
|
|
--- a/net/minecraft/server/level/PlayerChunk.java
|
|
|
|
+++ b/net/minecraft/server/level/PlayerChunk.java
|
2022-02-28 16:00:00 +01:00
|
|
|
@@ -37,6 +37,10 @@
|
2021-03-15 23:00:00 +01:00
|
|
|
import net.minecraft.world.level.chunk.ProtoChunkExtension;
|
|
|
|
import net.minecraft.world.level.lighting.LightEngine;
|
|
|
|
|
|
|
|
+// CraftBukkit start
|
|
|
|
+import net.minecraft.server.MinecraftServer;
|
|
|
|
+// CraftBukkit end
|
|
|
|
+
|
|
|
|
public class PlayerChunk {
|
|
|
|
|
2021-06-11 07:00:00 +02:00
|
|
|
public static final Either<IChunkAccess, PlayerChunk.Failure> UNLOADED_CHUNK = Either.right(PlayerChunk.Failure.UNLOADED);
|
2022-02-28 16:00:00 +01:00
|
|
|
@@ -75,11 +79,11 @@
|
2021-06-11 07:00:00 +02:00
|
|
|
this.fullChunkFuture = PlayerChunk.UNLOADED_LEVEL_CHUNK_FUTURE;
|
|
|
|
this.tickingChunkFuture = PlayerChunk.UNLOADED_LEVEL_CHUNK_FUTURE;
|
|
|
|
this.entityTickingChunkFuture = PlayerChunk.UNLOADED_LEVEL_CHUNK_FUTURE;
|
|
|
|
- this.chunkToSave = CompletableFuture.completedFuture((Object) null);
|
|
|
|
+ this.chunkToSave = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error
|
|
|
|
this.chunkToSaveHistory = null;
|
|
|
|
this.blockChangedLightSectionFilter = new BitSet();
|
|
|
|
this.skyChangedLightSectionFilter = new BitSet();
|
|
|
|
- this.pendingFullStateConfirmation = CompletableFuture.completedFuture((Object) null);
|
|
|
|
+ this.pendingFullStateConfirmation = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error
|
|
|
|
this.pos = chunkcoordintpair;
|
|
|
|
this.levelHeightAccessor = levelheightaccessor;
|
2019-04-23 04:00:00 +02:00
|
|
|
this.lightEngine = lightengine;
|
2022-02-28 16:00:00 +01:00
|
|
|
@@ -117,17 +121,17 @@
|
2019-04-23 04:00:00 +02:00
|
|
|
@Nullable
|
2021-11-21 23:00:00 +01:00
|
|
|
public Chunk getTickingChunk() {
|
|
|
|
CompletableFuture<Either<Chunk, PlayerChunk.Failure>> completablefuture = this.getTickingChunkFuture();
|
2019-04-23 04:00:00 +02:00
|
|
|
- Either<Chunk, PlayerChunk.Failure> either = (Either) completablefuture.getNow((Object) null);
|
|
|
|
+ Either<Chunk, PlayerChunk.Failure> either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error
|
|
|
|
|
|
|
|
- return either == null ? null : (Chunk) either.left().orElse((Object) null);
|
|
|
|
+ return either == null ? null : (Chunk) either.left().orElse(null); // CraftBukkit - decompile error
|
|
|
|
}
|
|
|
|
|
2019-07-20 01:00:00 +02:00
|
|
|
@Nullable
|
2022-02-28 16:00:00 +01:00
|
|
|
public Chunk getFullChunk() {
|
|
|
|
CompletableFuture<Either<Chunk, PlayerChunk.Failure>> completablefuture = this.getFullChunkFuture();
|
|
|
|
- Either<Chunk, PlayerChunk.Failure> either = (Either) completablefuture.getNow((Object) null);
|
|
|
|
+ Either<Chunk, PlayerChunk.Failure> either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error
|
|
|
|
|
|
|
|
- return either == null ? null : (Chunk) either.left().orElse((Object) null);
|
|
|
|
+ return either == null ? null : (Chunk) either.left().orElse(null); // CraftBukkit - decompile error
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
@@ -172,6 +176,7 @@
|
2020-08-20 10:48:38 +02:00
|
|
|
if (chunk != null) {
|
2021-06-11 07:00:00 +02:00
|
|
|
int i = this.levelHeightAccessor.getSectionIndex(blockposition.getY());
|
2020-08-20 10:48:38 +02:00
|
|
|
|
2021-06-11 07:00:00 +02:00
|
|
|
+ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
|
|
|
|
if (this.changedBlocksPerSection[i] == null) {
|
|
|
|
this.hasChangedSections = true;
|
2021-11-21 23:00:00 +01:00
|
|
|
this.changedBlocksPerSection[i] = new ShortOpenHashSet();
|
2022-02-28 16:00:00 +01:00
|
|
|
@@ -368,7 +373,7 @@
|
2021-06-11 07:00:00 +02:00
|
|
|
this.pendingFullStateConfirmation = completablefuture1;
|
|
|
|
completablefuture.thenAccept((either) -> {
|
|
|
|
either.ifLeft((chunk) -> {
|
|
|
|
- completablefuture1.complete((Object) null);
|
|
|
|
+ completablefuture1.complete(null); // CraftBukkit - decompile error
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2022-02-28 16:00:00 +01:00
|
|
|
@@ -385,6 +390,30 @@
|
2021-06-11 07:00:00 +02:00
|
|
|
boolean flag1 = this.ticketLevel <= PlayerChunkMap.MAX_CHUNK_DISTANCE;
|
2021-11-21 23:00:00 +01:00
|
|
|
PlayerChunk.State playerchunk_state = getFullChunkStatus(this.oldTicketLevel);
|
|
|
|
PlayerChunk.State playerchunk_state1 = getFullChunkStatus(this.ticketLevel);
|
2019-05-16 01:11:20 +02:00
|
|
|
+ // CraftBukkit start
|
|
|
|
+ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
|
2021-11-21 23:00:00 +01:00
|
|
|
+ if (playerchunk_state.isOrAfter(PlayerChunk.State.BORDER) && !playerchunk_state1.isOrAfter(PlayerChunk.State.BORDER)) {
|
|
|
|
+ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
2020-03-03 02:19:06 +01:00
|
|
|
+ Chunk chunk = (Chunk)either.left().orElse(null);
|
|
|
|
+ if (chunk != null) {
|
|
|
|
+ playerchunkmap.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.
|
2021-11-21 23:00:00 +01:00
|
|
|
+ chunk.setUnsaved(true);
|
2020-03-03 02:19:06 +01:00
|
|
|
+ chunk.unloadCallback();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }).exceptionally((throwable) -> {
|
|
|
|
+ // ensure exceptions are printed, by default this is not the case
|
2022-02-28 16:00:00 +01:00
|
|
|
+ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + PlayerChunk.this.pos, throwable);
|
2020-03-03 02:19:06 +01:00
|
|
|
+ return null;
|
|
|
|
+ });
|
2019-07-13 20:19:44 +02:00
|
|
|
+
|
|
|
|
+ // Run callback right away if the future was already done
|
|
|
|
+ playerchunkmap.callbackExecutor.run();
|
2019-05-16 01:11:20 +02:00
|
|
|
+ }
|
|
|
|
+ // CraftBukkit end
|
|
|
|
|
2019-05-27 22:30:00 +02:00
|
|
|
if (flag) {
|
2021-11-21 23:00:00 +01:00
|
|
|
Either<IChunkAccess, PlayerChunk.Failure> either = Either.right(new PlayerChunk.Failure() {
|
2022-02-28 16:00:00 +01:00
|
|
|
@@ -455,6 +484,26 @@
|
2019-05-16 01:11:20 +02:00
|
|
|
|
2021-11-21 23:00:00 +01:00
|
|
|
this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel);
|
2019-05-16 01:11:20 +02:00
|
|
|
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.
|
2021-11-21 23:00:00 +01:00
|
|
|
+ if (!playerchunk_state.isOrAfter(PlayerChunk.State.BORDER) && playerchunk_state1.isOrAfter(PlayerChunk.State.BORDER)) {
|
|
|
|
+ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
2020-03-03 02:19:06 +01:00
|
|
|
+ Chunk chunk = (Chunk)either.left().orElse(null);
|
|
|
|
+ if (chunk != null) {
|
|
|
|
+ playerchunkmap.callbackExecutor.execute(() -> {
|
|
|
|
+ chunk.loadCallback();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }).exceptionally((throwable) -> {
|
|
|
|
+ // ensure exceptions are printed, by default this is not the case
|
2022-02-28 16:00:00 +01:00
|
|
|
+ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + PlayerChunk.this.pos, throwable);
|
2020-03-03 02:19:06 +01:00
|
|
|
+ return null;
|
|
|
|
+ });
|
2019-07-13 20:19:44 +02:00
|
|
|
+
|
|
|
|
+ // Run callback right away if the future was already done
|
|
|
|
+ playerchunkmap.callbackExecutor.run();
|
2019-05-16 01:11:20 +02:00
|
|
|
+ }
|
|
|
|
+ // CraftBukkit end
|
|
|
|
}
|
|
|
|
|
2021-11-21 23:00:00 +01:00
|
|
|
public static ChunkStatus getStatus(int i) {
|