aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0318-Entity-add-to-world-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches/0318-Entity-add-to-world-fixes.patch')
-rw-r--r--Spigot-Server-Patches/0318-Entity-add-to-world-fixes.patch96
1 files changed, 96 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0318-Entity-add-to-world-fixes.patch b/Spigot-Server-Patches/0318-Entity-add-to-world-fixes.patch
new file mode 100644
index 0000000000..9b8db42564
--- /dev/null
+++ b/Spigot-Server-Patches/0318-Entity-add-to-world-fixes.patch
@@ -0,0 +1,96 @@
+From caaa22ced1e3cc9e7c6c79192259a5436f1783e3 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+Date: Fri, 3 Aug 2018 22:47:46 -0400
+Subject: [PATCH] Entity add to world fixes
+
+1) Chunk Registration might kill an entity, don't add it to the world if it did!
+
+2) By default, entities are added to the world per slice iteration.
+This opens risk of the slices being manipulated during chunk add if an
+EntityAddToWorldEvent spawns an entity into this chunk.
+Fix this by differing entity add to world for all entities at the same time
+
+3) If a duplicate entity is attempted to add to the world of an entity, and
+the original entity is dead, overwrite it as the logic does for unloaod queued entities.
+
+diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
+index 01abe5e376..4502ece4dd 100644
+--- a/src/main/java/net/minecraft/server/Chunk.java
++++ b/src/main/java/net/minecraft/server/Chunk.java
+@@ -2,6 +2,8 @@ package net.minecraft.server;
+
+ // Paper start
+ import com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode;
++
++import java.util.Arrays;
+ import java.util.HashMap;
+ import java.util.UUID;
+ // Paper end
+@@ -957,15 +959,16 @@ public class Chunk implements IChunkAccess {
+ // Paper end
+
+ // CraftBukkit start
+- List<Entity> toRemove = new LinkedList<>();
+- this.world.a(entityslice.stream().filter((entity) -> {
+- if (this.needsDecoration && !CraftEventFactory.doEntityAddEventCalling(this.world, entity, CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { // Only call for new chunks
+- toRemove.add(entity);
+- return false;
+- }
+- return !(entity instanceof EntityHuman);
+- }));
+- entityslice.removeAll(toRemove);
++ this.world.addChunkEntities(entityslice.stream() // Paper - add all at same time to avoid entities adding to world modifying slice state, skip already added entities (not normal, but can happen)
++ // Paper start - Inline event into stream
++ .filter((entity) -> {
++ if (!this.needsDecoration) {
++ return true;
++ }
++ return CraftEventFactory.doEntityAddEventCalling(this.world, entity, CreatureSpawnEvent.SpawnReason.CHUNK_GEN);
++ })
++ // Paper end - Inline event into stream
++ .filter((entity) -> !(entity instanceof EntityHuman || entity.valid))); // Paper - add all at same time to avoid entities adding to world modifying slice state, skip already added entities (not normal, but can happen)
+ // CraftBukkit end
+ }
+
+diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
+index 3acea908c2..e31e366249 100644
+--- a/src/main/java/net/minecraft/server/World.java
++++ b/src/main/java/net/minecraft/server/World.java
+@@ -1037,6 +1037,7 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
+ }
+
+ this.getChunkAt(i, j).a(entity);
++ if (entity.dead) return false; // Paper - don't add dead entities, chunk registration may of killed it
+ this.entityList.add(entity);
+ this.b(entity);
+ return true;
+@@ -2434,9 +2435,13 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
+ return j;
+ }
+
++ public void addChunkEntities(Stream<Entity> collection) { a(collection); } // Paper - OBFHELPER
+ public void a(Stream<Entity> stream) {
+ org.spigotmc.AsyncCatcher.catchOp( "entity world add"); // Spigot
+ stream.forEach((entity) -> {
++ if (entity == null || entity.dead || entity.valid) { // Paper - prevent adding already added or dead entities
++ return;
++ }
+ this.entityList.add(entity);
+ this.b(entity);
+ });
+diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
+index 293818b196..4cda6cee2b 100644
+--- a/src/main/java/net/minecraft/server/WorldServer.java
++++ b/src/main/java/net/minecraft/server/WorldServer.java
+@@ -967,7 +967,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
+ if (this.entitiesByUUID.containsKey(uuid)) {
+ Entity entity1 = (Entity) this.entitiesByUUID.get(uuid);
+
+- if (this.g.contains(entity1)) {
++ if (this.g.contains(entity1) || entity1.dead) { // Paper - if dupe is dead, overwrite
+ this.g.remove(entity1);
+ } else {
+ if (!(entity instanceof EntityHuman)) {
+--
+2.21.0
+