Paper/Spigot-Server-Patches/0422-Ensure-Entity-is-never-double-registered.patch
Mariell Hoversholm 654b792caf Updated Upstream (CraftBukkit)
Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

CraftBukkit Changes:
a339310c #755: Fix NPE when calling getInventory() for virtual EnderChests
2577f9bf Increase outdated build delay
1dabfdc8 #754: Fix pre-1.16 serialized SkullMeta being broken on 1.16+, losing textures
2020-09-27 11:04:51 -04:00

80 Zeilen
3.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
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
index eaffc6ee2d677dd69f81a2822049a06ec0325149..ca85df9d05e763586a0cf269e997fbf629c44c98 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -59,6 +59,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
}
// 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
index 85b1187cf71760f433ea0f8b972bcc9e43dbde2a..bd7c3c32809b79218d857f9ae6b4c23220d29ea5 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -531,6 +531,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
Entity entity2;
while ((entity2 = (Entity) this.entitiesToAdd.poll()) != null) {
+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers
this.registerEntity(entity2);
}
@@ -1286,6 +1287,19 @@ public class WorldServer extends World implements GeneratorAccessSeed {
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 )
{
@@ -1352,9 +1366,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
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) {
EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ();