mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-26 12:36:07 +01:00
116 lines
6.3 KiB
Diff
116 lines
6.3 KiB
Diff
--- a/net/minecraft/server/PlayerChunk.java
|
|
+++ b/net/minecraft/server/PlayerChunk.java
|
|
@@ -44,7 +44,7 @@
|
|
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
|
this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
|
this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
|
- this.chunkSave = CompletableFuture.completedFuture((Object) null);
|
|
+ this.chunkSave = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error
|
|
this.dirtyBlocks = new ShortSet[16];
|
|
this.location = chunkcoordintpair;
|
|
this.lightEngine = lightengine;
|
|
@@ -56,6 +56,15 @@
|
|
this.a(i);
|
|
}
|
|
|
|
+ // CraftBukkit start
|
|
+ public Chunk getFullChunk() {
|
|
+ if (!getChunkState(this.oldTicketLevel).isAtLeast(PlayerChunk.State.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks
|
|
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> statusFuture = this.getStatusFutureUnchecked(ChunkStatus.FULL);
|
|
+ Either<IChunkAccess, PlayerChunk.Failure> either = (Either<IChunkAccess, PlayerChunk.Failure>) statusFuture.getNow(null);
|
|
+ return either == null ? null : (Chunk) either.left().orElse(null);
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) {
|
|
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = (CompletableFuture) this.statusFutures.get(chunkstatus.c());
|
|
|
|
@@ -81,9 +90,9 @@
|
|
@Nullable
|
|
public Chunk getChunk() {
|
|
CompletableFuture<Either<Chunk, PlayerChunk.Failure>> completablefuture = this.a();
|
|
- 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
|
|
@@ -216,7 +225,7 @@
|
|
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = (CompletableFuture) this.statusFutures.get(i);
|
|
|
|
if (completablefuture != null) {
|
|
- Either<IChunkAccess, PlayerChunk.Failure> either = (Either) completablefuture.getNow((Object) null);
|
|
+ Either<IChunkAccess, PlayerChunk.Failure> either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error
|
|
|
|
if (either == null || either.left().isPresent()) {
|
|
return completablefuture;
|
|
@@ -271,6 +280,30 @@
|
|
boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET;
|
|
PlayerChunk.State playerchunk_state = getChunkState(this.oldTicketLevel);
|
|
PlayerChunk.State playerchunk_state1 = getChunkState(this.ticketLevel);
|
|
+ // CraftBukkit start
|
|
+ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
|
|
+ if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) {
|
|
+ this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
|
+ 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.
|
|
+ chunk.setNeedsSaving(true);
|
|
+ chunk.unloadCallback();
|
|
+ });
|
|
+ }
|
|
+ }).exceptionally((throwable) -> {
|
|
+ // ensure exceptions are printed, by default this is not the case
|
|
+ MinecraftServer.LOGGER.fatal("Failed to schedule unload callback for chunk " + PlayerChunk.this.location, throwable);
|
|
+ return null;
|
|
+ });
|
|
+
|
|
+ // Run callback right away if the future was already done
|
|
+ playerchunkmap.callbackExecutor.run();
|
|
+ }
|
|
+ // CraftBukkit end
|
|
CompletableFuture completablefuture;
|
|
|
|
if (flag) {
|
|
@@ -302,7 +335,7 @@
|
|
if (flag2 && !flag3) {
|
|
completablefuture = this.fullChunkFuture;
|
|
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
|
- this.a(completablefuture.thenApply((either1) -> {
|
|
+ this.a(((CompletableFuture<Either<Chunk, PlayerChunk.Failure>>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error
|
|
playerchunkmap.getClass();
|
|
return either1.ifLeft(playerchunkmap::a);
|
|
}));
|
|
@@ -340,6 +373,26 @@
|
|
|
|
this.u.a(this.location, this::k, this.ticketLevel, this::d);
|
|
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 (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) {
|
|
+ this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
|
+ 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
|
|
+ MinecraftServer.LOGGER.fatal("Failed to schedule load callback for chunk " + PlayerChunk.this.location, throwable);
|
|
+ return null;
|
|
+ });
|
|
+
|
|
+ // Run callback right away if the future was already done
|
|
+ playerchunkmap.callbackExecutor.run();
|
|
+ }
|
|
+ // CraftBukkit end
|
|
}
|
|
|
|
public static ChunkStatus getChunkStatus(int i) {
|