From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 31 Oct 2021 21:34:00 -0700
Subject: [PATCH] Async catch modifications to critical entity state

These used to be here from Spigot, but were dropped with 1.17.
Now in 1.17, this state is _even more_ critical than it was before,
so these must exist to catch stupid plugins.

diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
index 1f0eddb0f3ded42bf312f8933def2f5c9a964651..2d3aacdae95963385ea228e73a2073a6fd96e640 100644
--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
+++ b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
@@ -138,6 +138,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     private boolean addEntityUuid(T entity) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity add by UUID"); // Paper
         if (!this.knownUuids.add(entity.getUUID())) {
             // Paper start
             T conflict = this.visibleEntityStorage.getEntity(entity.getUUID());
@@ -166,6 +167,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     private boolean addEntity(T entity, boolean existing) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity add"); // Paper
         // Paper start - chunk system hooks
         if (existing) {
             // I don't want to know why this is a generic type.
@@ -222,19 +224,23 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     void startTicking(T entity) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity start ticking"); // Paper
         this.callbacks.onTickingStart(entity);
     }
 
     void stopTicking(T entity) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity stop ticking"); // Paper
         this.callbacks.onTickingEnd(entity);
     }
 
     void startTracking(T entity) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity start tracking"); // Paper
         this.visibleEntityStorage.add(entity);
         this.callbacks.onTrackingStart(entity);
     }
 
     void stopTracking(T entity) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity stop tracking"); // Paper
         this.callbacks.onTrackingEnd(entity);
         this.visibleEntityStorage.remove(entity);
     }
@@ -248,6 +254,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     public void updateChunkStatus(ChunkPos chunkPos, Visibility trackingStatus) {
+        org.spigotmc.AsyncCatcher.catchOp("Update chunk status"); // Paper
         long i = chunkPos.toLong();
 
         if (trackingStatus == Visibility.HIDDEN) {
@@ -292,6 +299,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     public void ensureChunkQueuedForLoad(long chunkPos) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity chunk save"); // Paper
         PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_b = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(chunkPos);
 
         if (persistententitysectionmanager_b == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) {
@@ -336,6 +344,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     private void requestChunkLoad(long chunkPos) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity chunk load request"); // Paper
         this.chunkLoadStatuses.put(chunkPos, PersistentEntitySectionManager.ChunkLoadStatus.PENDING);
         ChunkPos chunkcoordintpair = new ChunkPos(chunkPos);
         CompletableFuture completablefuture = this.permanentStorage.loadEntities(chunkcoordintpair);
@@ -349,6 +358,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     private boolean processChunkUnload(long chunkPos) {
+        org.spigotmc.AsyncCatcher.catchOp("Entity chunk unload process"); // Paper
         boolean flag = this.storeChunkSections(chunkPos, (entityaccess) -> {
             entityaccess.getPassengersAndSelf().forEach(this::unloadEntity);
         }, true); // CraftBukkit - add boolean for event call
@@ -373,6 +383,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     private void processPendingLoads() {
+        org.spigotmc.AsyncCatcher.catchOp("Entity chunk process pending loads"); // Paper
         ChunkEntities<T> chunkentities; // CraftBukkit - decompile error
 
         while ((chunkentities = (ChunkEntities) this.loadingInbox.poll()) != null) {
@@ -389,6 +400,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     public void tick() {
+        org.spigotmc.AsyncCatcher.catchOp("Entity manager tick"); // Paper
         this.processPendingLoads();
         this.processUnloads();
     }
@@ -409,6 +421,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     public void autoSave() {
+        org.spigotmc.AsyncCatcher.catchOp("Entity manager autosave"); // Paper
         this.getAllChunksToSave().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error
             boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN;
 
@@ -423,6 +436,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
     }
 
     public void saveAll() {
+        org.spigotmc.AsyncCatcher.catchOp("Entity manager save"); // Paper
         LongSet longset = this.getAllChunksToSave();
 
         while (!longset.isEmpty()) {
@@ -530,6 +544,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
             long i = SectionPos.asLong(blockposition); final long newSectionPos = i; // Paper - diff on change, new position section
 
             if (i != this.currentSectionKey) {
+                org.spigotmc.AsyncCatcher.catchOp("Entity move"); // Paper
                 PersistentEntitySectionManager.this.entitySliceManager.moveEntity((Entity)this.entity); // Paper
                 Visibility visibility = this.currentSection.getStatus(); final Visibility oldVisibility = visibility; // Paper - diff on change - this should be OLD section visibility
                 // Paper start
@@ -604,6 +619,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
 
         @Override
         public void onRemove(Entity.RemovalReason reason) {
+            org.spigotmc.AsyncCatcher.catchOp("Entity remove"); // Paper
             if (!this.currentSection.remove(this.entity)) {
                 PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), reason});
             }