diff --git a/Spigot-Server-Patches/0397-Fix-some-generation-concurrency-issues.patch b/Spigot-Server-Patches/0397-Fix-some-generation-concurrency-issues.patch new file mode 100644 index 0000000000..dc24851fd2 --- /dev/null +++ b/Spigot-Server-Patches/0397-Fix-some-generation-concurrency-issues.patch @@ -0,0 +1,213 @@ +From 74fb35c1ea9c0283e1e3bb22b9049d2b4252d315 Mon Sep 17 00:00:00 2001 +From: Shane Freeder +Date: Fri, 24 May 2019 07:53:16 +0100 +Subject: [PATCH] Fix some generation concurrency issues + + +diff --git a/src/main/java/net/minecraft/server/DefinedStructureManager.java b/src/main/java/net/minecraft/server/DefinedStructureManager.java +index 6aa0ca3959..ed9b5c63f0 100644 +--- a/src/main/java/net/minecraft/server/DefinedStructureManager.java ++++ b/src/main/java/net/minecraft/server/DefinedStructureManager.java +@@ -20,7 +20,7 @@ import org.apache.logging.log4j.Logger; + public class DefinedStructureManager implements IResourcePackListener { + + private static final Logger LOGGER = LogManager.getLogger(); +- private final Map b = Maps.newHashMap(); ++ private final Map b = Maps.newConcurrentMap(); // Paper + private final DataFixer c; + private final MinecraftServer d; + private final java.nio.file.Path e; +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index c04d73e738..e4f2aeed29 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -101,6 +101,23 @@ public abstract class World implements IIBlockAccess, GeneratorAccess, AutoClose + private int tileTickPosition; + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here ++ // Paper start - yes this is hacky as shit ++ RegionLimitedWorldAccess regionLimited; ++ World originalWorld; ++ public World regionLimited(RegionLimitedWorldAccess limitedWorldAccess) { ++ try { ++ World clone = (World) super.clone(); ++ clone.regionLimited = limitedWorldAccess; ++ clone.originalWorld = this; ++ return clone; ++ } catch (CloneNotSupportedException e1) { ++ } ++ return null; ++ } ++ ChunkCoordIntPair[] strongholdCoords; ++ List strongholdStuctures = Lists.newArrayList(); ++ final java.lang.Object stuctureLock = new Object(); ++ // Paper end + + public CraftWorld getWorld() { + return this.world; +diff --git a/src/main/java/net/minecraft/server/WorldGenStronghold.java b/src/main/java/net/minecraft/server/WorldGenStronghold.java +index eca27e52e9..fb3463fcce 100644 +--- a/src/main/java/net/minecraft/server/WorldGenStronghold.java ++++ b/src/main/java/net/minecraft/server/WorldGenStronghold.java +@@ -10,10 +10,12 @@ import javax.annotation.Nullable; + + public class WorldGenStronghold extends StructureGenerator { + ++ /* // Paper start - no shared state + private boolean a; + private ChunkCoordIntPair[] aS; + private final List aT = Lists.newArrayList(); + private long aU; ++ */ + + public WorldGenStronghold(Function, ? extends WorldGenFeatureEmptyConfiguration> function) { + super(function); +@@ -21,16 +23,22 @@ public class WorldGenStronghold extends StructureGenerator chunkgenerator, Random random, int i, int j) { ++ // Paper start ++ /* + if (this.aU != chunkgenerator.getSeed()) { + this.d(); + } ++ */ ++ final World world = chunkgenerator.getWorld(); + +- if (!this.a) { ++ synchronized (world.stuctureLock) { ++ if ( world.strongholdCoords == null) { + this.a(chunkgenerator); +- this.a = true; +- } ++ // this.a = true; ++ }} ++ // Paper end + +- ChunkCoordIntPair[] achunkcoordintpair = this.aS; ++ ChunkCoordIntPair[] achunkcoordintpair = world.strongholdCoords; // Paper + int k = achunkcoordintpair.length; + + for (int l = 0; l < k; ++l) { +@@ -45,9 +53,11 @@ public class WorldGenStronghold extends StructureGenerator chunkgenerator, BlockPosition blockposition, int i, boolean flag) { + if (!chunkgenerator.getWorldChunkManager().a(this)) { + return null; + } else { ++ // Paper start - no shared state ++ /* + if (this.aU != world.getSeed()) { + this.d(); + } ++ */ + +- if (!this.a) { +- this.a(chunkgenerator); +- this.a = true; ++ synchronized (world.stuctureLock) { ++ if ( world.strongholdCoords == null) { ++ this.a(chunkgenerator); ++ //this.a = true; ++ } + } ++ // Paper end + + BlockPosition blockposition1 = null; + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); + double d0 = Double.MAX_VALUE; +- ChunkCoordIntPair[] achunkcoordintpair = this.aS; ++ ChunkCoordIntPair[] achunkcoordintpair = world.strongholdCoords; // Paper + int j = achunkcoordintpair.length; + + for (int k = 0; k < j; ++k) { +@@ -106,7 +123,7 @@ public class WorldGenStronghold extends StructureGenerator chunkgenerator) { +- this.aU = chunkgenerator.getSeed(); ++ //this.aU = chunkgenerator.getSeed(); // Paper + List list = Lists.newArrayList(); + Iterator iterator = IRegistry.BIOME.iterator(); + +@@ -122,15 +139,15 @@ public class WorldGenStronghold extends StructureGenerator= i1) { +- this.aS[l1] = new ChunkCoordIntPair(i2, j2); ++ strongholdCoords[l1] = new ChunkCoordIntPair(i2, j2); // Paper + } + + d0 += 6.283185307179586D / (double) k; +@@ -165,7 +182,7 @@ public class WorldGenStronghold extends StructureGenerator