papermc/Spigot-Server-Patches/0391-Fix-some-generation-concurrency-issues.patch
Shane Freeder 0708fa363b
Updated Upstream (CraftBukkit/Spigot)
Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

CraftBukkit Changes:
eb2e6578 SPIGOT-5116: Fix concurrent modification exception inside ChunkMapDistance
989f9b3d SPIGOT-4849: Fix server crash when accessing chunks during chunk load/unload/populate events
f554183c SPIGOT-5171: Don't fire PlayerTeleportEvent if not actually moving
2349feb8 SPIGOT-5163: Cancelling PlayerBucketFillEvent visually removes the targeted block

Spigot Changes:
9a643a6a Remove DataWatcher Locking
2019-07-16 23:09:32 +01:00

213 lines
9.1 KiB
Diff

From b702eef95eabfe9dcc0dd66df1844fc26399ae47 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
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 6aa0ca395..ed9b5c63f 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<MinecraftKey, DefinedStructure> b = Maps.newHashMap();
+ private final Map<MinecraftKey, DefinedStructure> 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 2eed9c2ec..f0e8acdd1 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<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
public java.util.ArrayDeque<BlockRedstoneTorch.RedstoneUpdateInfo> 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<StructureStart> 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 eca27e52e..fb3463fcc 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<WorldGenFeatureEmptyConfiguration> {
+ /* // Paper start - no shared state
private boolean a;
private ChunkCoordIntPair[] aS;
private final List<StructureStart> aT = Lists.newArrayList();
private long aU;
+ */
public WorldGenStronghold(Function<Dynamic<?>, ? extends WorldGenFeatureEmptyConfiguration> function) {
super(function);
@@ -21,16 +23,22 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
@Override
public boolean a(ChunkGenerator<?> 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<WorldGenFeatureEmptyC
}
private void d() {
+ /* // Paper
this.a = false;
this.aS = null;
this.aT.clear();
+ */ // Paper
}
@Override
@@ -65,25 +75,32 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
return 8;
}
+
@Nullable
@Override
public BlockPosition getNearestGeneratedFeature(World world, ChunkGenerator<? extends GeneratorSettingsDefault> 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<WorldGenFeatureEmptyC
}
private void a(ChunkGenerator<?> chunkgenerator) {
- this.aU = chunkgenerator.getSeed();
+ //this.aU = chunkgenerator.getSeed(); // Paper
List<BiomeBase> list = Lists.newArrayList();
Iterator iterator = IRegistry.BIOME.iterator();
@@ -122,15 +139,15 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
int j = chunkgenerator.getSettings().f();
int k = chunkgenerator.getSettings().g();
- this.aS = new ChunkCoordIntPair[j];
+ ChunkCoordIntPair[] strongholdCoords = chunkgenerator.getWorld().strongholdCoords = new ChunkCoordIntPair[j]; // Paper
int l = 0;
- Iterator iterator1 = this.aT.iterator();
+ Iterator iterator1 = chunkgenerator.getWorld().strongholdStuctures.iterator(); // Paper
while (iterator1.hasNext()) {
StructureStart structurestart = (StructureStart) iterator1.next();
- if (l < this.aS.length) {
- this.aS[l++] = new ChunkCoordIntPair(structurestart.f(), structurestart.g());
+ if (l < strongholdCoords.length) { // Paper
+ strongholdCoords[l++] = new ChunkCoordIntPair(structurestart.f(), structurestart.g()); // Paper
}
}
@@ -140,11 +157,11 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
double d0 = random.nextDouble() * 3.141592653589793D * 2.0D;
int i1 = l;
- if (l < this.aS.length) {
+ if (l < strongholdCoords.length) { // Paper
int j1 = 0;
int k1 = 0;
- for (int l1 = 0; l1 < this.aS.length; ++l1) {
+ for (int l1 = 0; l1 < strongholdCoords.length; ++l1) { // Paper
double d1 = (double) (4 * i + i * k1 * 6) + (random.nextDouble() - 0.5D) * (double) i * 2.5D;
int i2 = (int) Math.round(Math.cos(d0) * d1);
int j2 = (int) Math.round(Math.sin(d0) * d1);
@@ -156,7 +173,7 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
}
if (l1 >= 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<WorldGenFeatureEmptyC
++k1;
j1 = 0;
k += 2 * k / (k1 + 1);
- k = Math.min(k, this.aS.length - l1);
+ k = Math.min(k, strongholdCoords.length - l1);
d0 += random.nextDouble() * 3.141592653589793D * 2.0D;
}
}
@@ -207,7 +224,7 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
this.a(chunkgenerator.getSeaLevel(), this.d, 10);
} while (this.b.isEmpty() || worldgenstrongholdpieces_worldgenstrongholdstart.b == null);
- ((WorldGenStronghold) this.k()).aT.add(this);
+ chunkgenerator.getWorld().strongholdStuctures.add(this); // Paper - this worries me, this is never cleared, even in vanilla (world seed never changes "world", and that appears to be the only relevant world)
}
}
}
--
2.22.0