From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Sat, 19 Sep 2020 15:29:16 -0700
Subject: [PATCH] Do not allow ticket level changes while unloading
 playerchunks

Sync loading the chunk at this stage would cause it to load
older data, as well as screwing our region state.

diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 0e5e7a321dc7066444d92387968a7c41cb3a8470..ce0bb4d228a73d8353d67828529879e1c99682f9 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -815,6 +815,7 @@ public class ChunkProviderServer extends IChunkProvider {
 
     public boolean tickDistanceManager() { // Paper - private -> public
         if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper
+        if (this.playerChunkMap.unloadingPlayerChunk) { MinecraftServer.LOGGER.fatal("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Tuinity
         co.aikar.timings.MinecraftTimings.distanceManagerTick.startTiming(); try { // Tuinity - add timings for distance manager
         boolean flag = this.chunkMapDistance.a(this.playerChunkMap);
         boolean flag1 = this.playerChunkMap.b();
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index d829feb9f17c5412e63b2481af968391f38298d2..94da0b4cb9a790f866bcd3b11a61ae0c0faa1dc5 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -776,6 +776,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
     @Nullable
     private PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k) {
         com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Chunk holder update"); // Tuinity
+        if (this.unloadingPlayerChunk) { MinecraftServer.LOGGER.fatal("Cannot tick distance manager while unloading playerchunks", new Throwable()); throw new IllegalStateException("Cannot tick distance manager while unloading playerchunks"); } // Tuinity
         if (k > PlayerChunkMap.GOLDEN_TICKET && j > PlayerChunkMap.GOLDEN_TICKET) {
             return playerchunk;
         } else {
@@ -1033,6 +1034,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
     }
     // Paper end
 
+    boolean unloadingPlayerChunk = false; // Tuinity - do not allow ticket level changes while unloading chunks
+
     private void a(long i, PlayerChunk playerchunk) {
         CompletableFuture<IChunkAccess> completablefuture = playerchunk.getChunkSave();
         Consumer<IChunkAccess> consumer = (ichunkaccess) -> { // CraftBukkit - decompile error
@@ -1041,6 +1044,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
             if (completablefuture1 != completablefuture) {
                 this.a(i, playerchunk);
             } else {
+                // Tuinity start - do not allow ticket level changes while unloading chunks
+                org.spigotmc.AsyncCatcher.catchOp("playerchunk unload");
+                boolean unloadingBefore = this.unloadingPlayerChunk;
+                this.unloadingPlayerChunk = true;
+                try {
+                // Tuinity end - do not allow ticket level changes while unloading chunks
                 // Tuinity start
                 boolean removed;
                 if ((removed = this.pendingUnload.remove(i, playerchunk)) && ichunkaccess != null) { // Tuinity end
@@ -1070,6 +1079,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
                 } else if (removed) { // Tuinity start
                     this.dataRegionManager.removeChunk(playerchunk.location.x, playerchunk.location.z);
                 } // Tuinity end
+                } finally { this.unloadingPlayerChunk = unloadingBefore; } // Tuinity - do not allow ticket level changes while unloading chunks
 
             }
         };
