2020-05-06 11:48:49 +02:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
2020-03-31 09:04:47 +02:00
|
|
|
From: Aikar <aikar@aikar.co>
|
|
|
|
Date: Sun, 29 Mar 2020 18:26:14 -0400
|
|
|
|
Subject: [PATCH] Ensure Entity is never double registered
|
|
|
|
|
|
|
|
If something calls register twice, and the world is ticking, it could be
|
|
|
|
enqueued to add twice.
|
|
|
|
|
|
|
|
Vs behavior of non ticking of just overwriting state.
|
|
|
|
|
|
|
|
We will now simply log a warning when this happens instead of crashing the server.
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
2020-11-03 03:22:15 +01:00
|
|
|
index d728a3aae38c083fe8dfa28a8b8460545e99bcb9..e98b247df2f5b34bd1f15a483c8da2f76aa96384 100644
|
2020-03-31 09:04:47 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/Entity.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/Entity.java
|
2020-09-11 00:09:10 +02:00
|
|
|
@@ -59,6 +59,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
2020-03-31 09:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Paper start
|
|
|
|
+ boolean isQueuedForRegister = false;
|
|
|
|
public static Random SHARED_RANDOM = new Random() {
|
|
|
|
private boolean locked = false;
|
|
|
|
@Override
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
2020-11-03 03:22:15 +01:00
|
|
|
index 784381e117ea9e39f3dabedba35daf0a41b119c5..2b7b7a8282424ad3c99824af99b5527a59c48bdb 100644
|
2020-03-31 09:04:47 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
2020-11-03 03:22:15 +01:00
|
|
|
@@ -535,6 +535,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
|
2020-06-26 01:38:24 +02:00
|
|
|
Entity entity2;
|
2020-03-31 09:04:47 +02:00
|
|
|
|
2020-06-26 01:38:24 +02:00
|
|
|
while ((entity2 = (Entity) this.entitiesToAdd.poll()) != null) {
|
|
|
|
+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers
|
|
|
|
this.registerEntity(entity2);
|
2020-03-31 09:04:47 +02:00
|
|
|
}
|
2020-06-26 01:38:24 +02:00
|
|
|
|
2020-11-03 03:22:15 +01:00
|
|
|
@@ -1290,6 +1291,19 @@ public class WorldServer extends World implements GeneratorAccessSeed {
|
2020-03-31 09:04:47 +02:00
|
|
|
|
|
|
|
public void unregisterEntity(Entity entity) {
|
|
|
|
org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot
|
|
|
|
+ // Paper start - fix entity registration issues
|
|
|
|
+ if (entity instanceof EntityComplexPart) {
|
|
|
|
+ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways
|
|
|
|
+ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc.
|
|
|
|
+ this.entitiesById.remove(entity.getId(), entity);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (!entity.valid) {
|
|
|
|
+ // Someone called remove before we ever got added, cancel the add.
|
|
|
|
+ entity.isQueuedForRegister = false;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // Paper end
|
|
|
|
// Spigot start
|
|
|
|
if ( entity instanceof EntityHuman )
|
|
|
|
{
|
2020-11-03 03:22:15 +01:00
|
|
|
@@ -1356,9 +1370,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
|
2020-03-31 09:04:47 +02:00
|
|
|
|
|
|
|
private void registerEntity(Entity entity) {
|
|
|
|
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
|
|
|
|
+ // Paper start - don't double enqueue entity registration
|
|
|
|
+ //noinspection ObjectEquality
|
|
|
|
+ if (this.entitiesById.get(entity.getId()) == entity) {
|
|
|
|
+ LOGGER.error(entity + " was already registered!");
|
|
|
|
+ new Throwable().printStackTrace();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // Paper end
|
|
|
|
if (this.tickingEntities) {
|
|
|
|
- this.entitiesToAdd.add(entity);
|
|
|
|
+ if (!entity.isQueuedForRegister) { // Paper
|
|
|
|
+ this.entitiesToAdd.add(entity);
|
|
|
|
+ entity.isQueuedForRegister = true; // Paper
|
|
|
|
+ }
|
|
|
|
} else {
|
|
|
|
+ entity.isQueuedForRegister = false; // Paper
|
|
|
|
this.entitiesById.put(entity.getId(), entity);
|
|
|
|
if (entity instanceof EntityEnderDragon) {
|
2020-08-25 04:22:08 +02:00
|
|
|
EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ();
|