From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Thu, 18 Jun 2020 18:23:20 -0700 Subject: [PATCH] Prevent unload() calls removing tickets for sync loads diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 6d0c56e4071a990a3b168143e8ac73f8b5ed0379..d03ca9b30380209397aed5371686e0022bf631d5 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -734,6 +734,8 @@ public class ServerChunkCache extends ChunkSource { return completablefuture; } + private long syncLoadCounter; // Paper - prevent plugin unloads from removing our ticket + private CompletableFuture> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper start - add isUrgent - old sig left in place for dirty nms plugins return getChunkFutureMainThread(chunkX, chunkZ, leastStatus, create, false); @@ -752,9 +754,12 @@ public class ServerChunkCache extends ChunkSource { ChunkHolder.FullChunkStatus currentChunkState = ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); currentlyUnloading = (oldChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !currentChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); } + final Long identifier; // Paper - prevent plugin unloads from removing our ticket if (create && !currentlyUnloading) { // CraftBukkit end this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); + identifier = Long.valueOf(this.syncLoadCounter++); // Paper - prevent plugin unloads from removing our ticket + this.distanceManager.addTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper - prevent plugin unloads from removing our ticket if (isUrgent) this.distanceManager.markUrgent(chunkcoordintpair); // Paper - Chunk priority if (this.chunkAbsent(playerchunk, l)) { ProfilerFiller gameprofilerfiller = this.level.getProfiler(); @@ -765,13 +770,21 @@ public class ServerChunkCache extends ChunkSource { playerchunk = this.getVisibleChunkIfPresent(k); gameprofilerfiller.pop(); if (this.chunkAbsent(playerchunk, l)) { + this.distanceManager.removeTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); // Paper throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException("No chunk holder after ticket has been added"))); } } - } + } else { identifier = null; } // Paper - prevent plugin unloads from removing our ticket // Paper start - Chunk priority CompletableFuture> future = this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(leastStatus, this.chunkMap); + // Paper start - prevent plugin unloads from removing our ticket + if (create && !currentlyUnloading) { + future.thenAcceptAsync((either) -> { + ServerChunkCache.this.distanceManager.removeTicketAtLevel(TicketType.REQUIRED_LOAD, chunkcoordintpair, l, identifier); + }, ServerChunkCache.this.mainThreadProcessor); + } + // Paper end - prevent plugin unloads from removing our ticket if (isUrgent) { future.thenAccept(either -> this.distanceManager.clearUrgent(chunkcoordintpair)); } diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java index 3c1698ba0d3bc412ab957777d9b5211dbc555208..41ddcf6775f99c56cf4b13b284420061e5dd6bdc 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java @@ -31,6 +31,7 @@ public class TicketType { public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit public static final TicketType PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit public static final TicketType DELAY_UNLOAD = create("delay_unload", Long::compareTo, 300); // Paper + public static final TicketType REQUIRED_LOAD = create("required_load", Long::compareTo); // Paper - make sure getChunkAt does not fail public static TicketType create(String name, Comparator argumentComparator) { return new TicketType<>(name, argumentComparator, 0L);