From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 15 Mar 2021 22:25:48 -0700
Subject: [PATCH] Be aware of entity teleports when chunk checking entities

If an entity were to be teleported via the sync load
that occured from the getChunkAt call, we would either
add to the wrong chunk or add to both chunks! not good.

diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
index 84b4b7524064a4f0c175f34778e4e0d8004888ea..fcf9af44702f34d75185eee0b3259fe0e57001b1 100644
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
@@ -1572,7 +1572,35 @@ public class WorldServer extends World implements GeneratorAccessSeed {
 
                     entity.inChunk = false;
                 } else {
-                    this.getChunkAt(i, k).a(entity);
+                    // Tuinity start - gotta be careful here, sync load can teleport entity.
+                    Chunk chunk = this.getChunkIfLoaded(i, k);
+                    if (chunk == null) {
+                        // might teleport the entity, so be prepared.
+                        // at this point, we are NOT in a chunk. so CLEARLY mark that for a recursive call to see.
+                        entity.inChunk = false;
+                        // now load
+                        chunk = this.getChunkAt(i, k);
+                        // are we in a chunk now?
+                        if (entity.inChunk) {
+                            // yup we teleported and were added to another chunk. do not add to the current one!
+                            return;
+                        }
+                        // did we teleport but did not add to a chunk?
+                        // copied from start
+                        int in = MathHelper.floor(entity.locX() / 16.0D);
+                        int jn =  Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior
+                        int kn = MathHelper.floor(entity.locZ() / 16.0D);
+                        if (in != i || jn != j || kn != k) {
+                            // teleported but were not added to a chunk. try now, let the new call try to add again
+                            this.chunkCheck(entity);
+                            return;
+                        }
+
+                        // only now at this point have we verified the new load did not screw up our position, so
+                        // now we can add to the chunk
+                    }
+                    chunk.a(entity);
+                    // Tuinity end - gotta be careful here, sync load can teleport entity.
                 }
                 // Tuinity start
                 if (entity.inChunk && (oldRegionX != newRegionX || oldRegionZ != newRegionZ)) {
