mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-11 17:31:06 +01:00
1358d1e914
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 881e06e5 PR-725: Add Item Unlimited Lifetime APIs CraftBukkit Changes: 74c08312 SPIGOT-6962: Call EntityChangeBlockEvent when when FallingBlockEntity starts to fall 64db5126 SPIGOT-6959: Make /loot command ignore empty items for spawn 2d760831 Increase outdated build delay 9ed7e4fb SPIGOT-6138, SPIGOT-6415: Don't call CreatureSpawnEvent after cross-dimensional travel fc4ad813 SPIGOT-6895: Trees grown with applyBoneMeal() don't fire the StructureGrowthEvent 59733a2e SPIGOT-6961: Actually return a copy of the ItemMeta Spigot Changes: ffceeae3 SPIGOT-6956: Drop unload queue patch as attempt at fixing stop issue e19ddabd PR-1011: Add Item Unlimited Lifetime APIs 34d40b0e SPIGOT-2942: give command fires PlayerDropItemEvent, cancelling it causes Item Duplication
129 lines
7.5 KiB
Diff
129 lines
7.5 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Sat, 21 Jul 2018 08:25:40 -0400
|
|
Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues
|
|
|
|
Add -Ddebug.entities=true to your JVM flags to gain more information
|
|
|
|
1.17: Needs to be reworked for new entity storage system
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index 81eb73e9fde37e3b196bd899ecd4d614897d1a98..4206e1c96cdc7b7e324331681215f735688dd558 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -1353,6 +1353,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
} else {
|
|
ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas());
|
|
|
|
+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker
|
|
this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
|
|
playerchunkmap_entitytracker.updatePlayers(this.level.players());
|
|
if (entity instanceof ServerPlayer) {
|
|
@@ -1395,7 +1396,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
if (playerchunkmap_entitytracker1 != null) {
|
|
playerchunkmap_entitytracker1.broadcastRemoved();
|
|
}
|
|
-
|
|
+ entity.tracker = null; // Paper - We're no longer tracked
|
|
}
|
|
|
|
protected void tick() {
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
index 4d69b6b35f04c904ee9ca9c896baaa9892f8ef9c..5f58aa648a5f0c3e61f6d9d5853583ca003e3620 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
@@ -209,6 +209,9 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
|
public final LevelStorageSource.LevelStorageAccess convertable;
|
|
public final UUID uuid;
|
|
public boolean hasPhysicsEvent = true; // Paper
|
|
+ public static Throwable getAddToWorldStackTrace(Entity entity) {
|
|
+ return new Throwable(entity + " Added to world at " + new java.util.Date());
|
|
+ }
|
|
|
|
@Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI
|
|
return this.chunkSource.getChunk(x, z, false);
|
|
@@ -1099,7 +1102,28 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
|
// CraftBukkit start
|
|
private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
|
|
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
|
+ // Paper start
|
|
+ if (entity.valid) {
|
|
+ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable());
|
|
+
|
|
+ if (DEBUG_ENTITIES) {
|
|
+ Throwable thr = entity.addedToWorldStack;
|
|
+ if (thr == null) {
|
|
+ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace");
|
|
+ } else {
|
|
+ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr);
|
|
+ }
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+ // Paper end
|
|
if (entity.isRemoved()) {
|
|
+ // Paper start
|
|
+ if (DEBUG_ENTITIES) {
|
|
+ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit
|
|
+ getAddToWorldStackTrace(entity).printStackTrace();
|
|
+ }
|
|
+ // Paper end
|
|
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit
|
|
return false;
|
|
} else {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
index 919b66c88f21606348b20f02cc420d0ff1fa0f8b..ad2341ce26f976b4c45d91e8040bea5aef130f02 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -173,6 +173,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
|
|
public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
|
|
private CraftEntity bukkitEntity;
|
|
|
|
+ public @org.jetbrains.annotations.Nullable net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper
|
|
+ public @Nullable Throwable addedToWorldStack; // Paper - entity debug
|
|
public CraftEntity getBukkitEntity() {
|
|
if (this.bukkitEntity == null) {
|
|
this.bukkitEntity = CraftEntity.getEntity(this.level.getCraftServer(), this);
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
|
index 67566e5f95f7452d31bea485bdb91a4e1a32e5d5..dc2235824853a0d7ccbff51dd26a71e97fe90ba7 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
@@ -142,6 +142,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
public boolean pvpMode;
|
|
public boolean keepSpawnInMemory = true;
|
|
public org.bukkit.generator.ChunkGenerator generator;
|
|
+ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper
|
|
|
|
public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710
|
|
public boolean captureBlockStates = false;
|
|
diff --git a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
|
index e6b9f812e521abd552e0c7dc0429d5a62f2bfc35..f4731d69946871768ecf16149a47d2ef1cb3e910 100644
|
|
--- a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
|
+++ b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java
|
|
@@ -34,6 +34,26 @@ public class EntityLookup<T extends EntityAccess> {
|
|
UUID uUID = entity.getUUID();
|
|
if (this.byUuid.containsKey(uUID)) {
|
|
LOGGER.warn("Duplicate entity UUID {}: {}", uUID, entity);
|
|
+ // Paper start - extra debug info
|
|
+ if (entity instanceof net.minecraft.world.entity.Entity entityCast) {
|
|
+ if (net.minecraft.server.level.ServerLevel.DEBUG_ENTITIES) {
|
|
+ entityCast.addedToWorldStack = net.minecraft.server.level.ServerLevel.getAddToWorldStackTrace(entityCast);
|
|
+ }
|
|
+
|
|
+ T old = this.byUuid.get(entity.getUUID());
|
|
+ if (old instanceof net.minecraft.world.entity.Entity oldCast && old != null && oldCast.getId() != entity.getId() && oldCast.valid) {
|
|
+ LOGGER.error("Overwrote an existing entity " + oldCast + " with " + entity);
|
|
+ if (net.minecraft.server.level.ServerLevel.DEBUG_ENTITIES) {
|
|
+ if (oldCast.addedToWorldStack != null) {
|
|
+ oldCast.addedToWorldStack.printStackTrace();
|
|
+ } else {
|
|
+ LOGGER.error("Oddly, the old entity was not added to the world in the normal way. Plugins?");
|
|
+ }
|
|
+ entityCast.addedToWorldStack.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
} else {
|
|
this.byUuid.put(uUID, entity);
|
|
this.byId.put(entity.getId(), entity);
|