2021-06-11 14:02:28 +02:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Aikar <aikar@aikar.co>
|
|
|
|
Date: Sat, 21 Jul 2018 14:27:34 -0400
|
|
|
|
Subject: [PATCH] Duplicate UUID Resolve Option
|
|
|
|
|
|
|
|
Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24
|
|
|
|
which was added all the way back in March of 2016, it was unknown (potentially not at the time)
|
|
|
|
that an entity might actually change the seed of the random object.
|
|
|
|
|
|
|
|
At some point, EntitySquid did start setting the seed. Due to this shared random, this caused
|
|
|
|
every entity to use a Random object with a predictable seed.
|
|
|
|
|
|
|
|
This has caused entities to potentially generate with the same UUID....
|
|
|
|
|
|
|
|
Over the years, servers have had entities disappear, but no sign of trouble
|
|
|
|
because CraftBukkit removed the log lines indicating that something was wrong.
|
|
|
|
|
|
|
|
We have fixed the root issue causing duplicate UUID's, however we now have chunk
|
|
|
|
files full of entities that have the same UUID as another entity!
|
|
|
|
|
|
|
|
When these chunks load, the 2nd entity will not be added to the world correctly.
|
|
|
|
|
|
|
|
If that chunk loads in a different order in the future, then it will reverse and the
|
|
|
|
missing one is now the one added to the world and not the other. This results in very
|
|
|
|
inconsistent entity behavior.
|
|
|
|
|
|
|
|
This change allows you to recover any duplicate entity by generating a new UUID for it.
|
|
|
|
This also lets you delete them instead if you don't want to risk having new entities added to
|
|
|
|
the world that you previously did not see.
|
|
|
|
|
|
|
|
But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options.
|
|
|
|
|
|
|
|
It is recommended you regenerate the entities, as these were legit entities, and deserve your love.
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
2024-01-23 18:01:39 +01:00
|
|
|
index 304e3c177488773d488e5b82f65a7c16a3750a29..1ce59bd654cf4cb68d510b0f6a8d1a72d2761bf7 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
2024-01-23 18:01:39 +01:00
|
|
|
@@ -537,6 +537,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
2021-06-16 08:25:38 +02:00
|
|
|
entity.discard();
|
|
|
|
needsRemoval = true;
|
|
|
|
}
|
2024-01-21 12:53:04 +01:00
|
|
|
+ checkDupeUUID(world, entity); // Paper - duplicate uuid resolving
|
2021-06-16 08:25:38 +02:00
|
|
|
return !needsRemoval;
|
2023-09-22 22:13:57 +02:00
|
|
|
}), position); // Paper - rewrite chunk system
|
2021-06-16 08:25:38 +02:00
|
|
|
// CraftBukkit end
|
2024-01-23 18:01:39 +01:00
|
|
|
@@ -548,6 +549,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
2023-09-22 22:13:57 +02:00
|
|
|
throw new UnsupportedOperationException(); // Paper - rewrite chunk system
|
2021-06-11 14:02:28 +02:00
|
|
|
}
|
|
|
|
|
2024-01-21 12:53:04 +01:00
|
|
|
+ // Paper start - duplicate uuid resolving
|
2022-09-01 18:51:59 +02:00
|
|
|
+ // rets true if to prevent the entity from being added
|
|
|
|
+ public static boolean checkDupeUUID(ServerLevel level, Entity entity) {
|
2022-06-09 10:51:45 +02:00
|
|
|
+ io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode mode = level.paperConfig().entities.spawning.duplicateUuid.mode;
|
|
|
|
+ if (mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.WARN
|
|
|
|
+ && mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.DELETE
|
|
|
|
+ && mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.SAFE_REGEN) {
|
2022-09-01 18:51:59 +02:00
|
|
|
+ return false;
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+ Entity other = level.getEntity(entity.getUUID());
|
|
|
|
+
|
2022-09-01 18:51:59 +02:00
|
|
|
+ if (other == null || other == entity) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
2022-06-09 10:51:45 +02:00
|
|
|
+ if (mode == io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.isRemoved()
|
2021-06-16 08:25:38 +02:00
|
|
|
+ && Objects.equals(other.getEncodeId(), entity.getEncodeId())
|
2022-06-09 10:51:45 +02:00
|
|
|
+ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < level.paperConfig().entities.spawning.duplicateUuid.safeRegenDeleteRange
|
2021-06-11 14:02:28 +02:00
|
|
|
+ ) {
|
2021-06-16 08:25:38 +02:00
|
|
|
+ entity.discard();
|
2022-09-01 18:51:59 +02:00
|
|
|
+ return true;
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
2024-01-21 17:39:05 +01:00
|
|
|
+ if (!other.isRemoved()) {
|
2021-06-11 14:02:28 +02:00
|
|
|
+ switch (mode) {
|
|
|
|
+ case SAFE_REGEN: {
|
2022-07-27 21:49:24 +02:00
|
|
|
+ entity.setUUID(java.util.UUID.randomUUID());
|
2021-06-11 14:02:28 +02:00
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case DELETE: {
|
2021-06-16 08:25:38 +02:00
|
|
|
+ entity.discard();
|
2022-09-01 18:51:59 +02:00
|
|
|
+ return true;
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
2022-09-01 18:51:59 +02:00
|
|
|
+ return false;
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
2024-01-21 12:53:04 +01:00
|
|
|
+ // Paper end - duplicate uuid resolving
|
2021-06-16 08:25:38 +02:00
|
|
|
public CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> prepareTickingChunk(ChunkHolder holder) {
|
2023-09-22 22:13:57 +02:00
|
|
|
throw new UnsupportedOperationException(); // Paper - rewrite chunk system
|
|
|
|
}
|