97 lines
4.7 KiB
Diff
97 lines
4.7 KiB
Diff
From f915d35b9a42d9b6f78a2eaf785a90339988fa75 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
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
|
|
|