From 3e7890be06d39b0159a36c5b5a5e59e2553f2217 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Thu, 29 Jun 2023 17:41:32 +0200
Subject: [PATCH] Hotfix double entity removal making entity scheduler retire
 call The assumption that the setRemoved method will never be called more than
 once is flawed, considering even vanilla code seems to indicate it might
 happen. Especially with plugins, throwing an exception is not something
 reasonably maintainable across all the places it *could* happen. If it is
 called a second time after already having been removed due to changing
 dimensions, that's definitely bad, so no extra check for that Fixes #9420

---
 .../server/Folia-scheduler-and-owned-region-API.patch  | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/patches/server/Folia-scheduler-and-owned-region-API.patch b/patches/server/Folia-scheduler-and-owned-region-API.patch
index 7ffd95500b..223843d721 100644
--- a/patches/server/Folia-scheduler-and-owned-region-API.patch
+++ b/patches/server/Folia-scheduler-and-owned-region-API.patch
@@ -1194,12 +1194,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
          this.remove(Entity.RemovalReason.DISCARDED);
      }
  
+@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+             return;
+         }
+         // Paper end - rewrite chunk system
++        final boolean alreadyRemoved = this.removalReason != null;
+         if (this.removalReason == null) {
+             this.removalReason = reason;
+         }
 @@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
  
          if (reason != RemovalReason.UNLOADED_TO_CHUNK) this.getPassengers().forEach(Entity::stopRiding); // Paper - chunk system - don't adjust passenger state when unloading, it's just not safe (and messes with our logic in entity chunk unload)
          this.levelCallback.onRemove(reason);
 +        // Paper start - Folia schedulers
-+        if (!(this instanceof ServerPlayer) && reason != RemovalReason.CHANGED_DIMENSION) {
++        if (!(this instanceof ServerPlayer) && reason != RemovalReason.CHANGED_DIMENSION && !alreadyRemoved) {
 +            // Players need to be special cased, because they are regularly removed from the world
 +            this.retireScheduler();
 +        }