From 0000000000000000000000000000000000000000 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/World.java b/src/main/java/net/minecraft/server/World.java index ee08cdcffc9237ee4154b7c756ba032b7723bd1f..74709dff3f87e929f1583be524d4e53ad3be6728 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -86,6 +86,23 @@ public abstract class World implements GeneratorAccess, AutoCloseable { 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/WorldGenFeatureStateProviderWeighted.java b/src/main/java/net/minecraft/server/WorldGenFeatureStateProviderWeighted.java index 22e14fe1e98c8439f8db74c9464137a497fdaf7c..e2af6d43b2eafeecad8fd070fc70195c7b0bb93f 100644 --- a/src/main/java/net/minecraft/server/WorldGenFeatureStateProviderWeighted.java +++ b/src/main/java/net/minecraft/server/WorldGenFeatureStateProviderWeighted.java @@ -23,18 +23,18 @@ public class WorldGenFeatureStateProviderWeighted extends WorldGenFeatureStatePr this(new WeightedList<>(dynamic.get("entries").orElseEmptyList(), IBlockData::a)); } - public WorldGenFeatureStateProviderWeighted a(IBlockData iblockdata, int i) { + public synchronized WorldGenFeatureStateProviderWeighted a(IBlockData iblockdata, int i) { // Paper this.b.a(iblockdata, i); return this; } @Override - public IBlockData a(Random random, BlockPosition blockposition) { + public synchronized IBlockData a(Random random, BlockPosition blockposition) { // Paper return (IBlockData) this.b.b(random); } @Override - public <T> T a(DynamicOps<T> dynamicops) { + public synchronized <T> T a(DynamicOps<T> dynamicops) { // Paper Builder<T, T> builder = ImmutableMap.builder(); builder.put(dynamicops.createString("type"), dynamicops.createString(IRegistry.t.getKey(this.a).toString())).put(dynamicops.createString("entries"), this.b.a(dynamicops, (iblockdata) -> { diff --git a/src/main/java/net/minecraft/server/WorldGenStronghold.java b/src/main/java/net/minecraft/server/WorldGenStronghold.java index fc4348b60242e4a9d8612c3b8ce01711c32f4b1c..44be7169ffd5961df28d21a319d2cc7569662baf 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[] aq; private final List<StructureStart> ar = Lists.newArrayList(); private long as; + */ public WorldGenStronghold(Function<Dynamic<?>, ? extends WorldGenFeatureEmptyConfiguration> function) { super(function); @@ -21,16 +23,22 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC @Override public boolean a(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int i, int j, BiomeBase biomebase) { + // Paper start + /* if (this.as != 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.aq; + 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.aq = null; this.ar.clear(); + */ // Paper } @Override @@ -65,25 +75,32 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC return 8; } + @Nullable @Override public synchronized 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.as != 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.aq; + 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.as = chunkgenerator.getSeed(); + //this.as = 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.aq = new ChunkCoordIntPair[j]; + ChunkCoordIntPair[] strongholdCoords = chunkgenerator.getWorld().strongholdCoords = new ChunkCoordIntPair[j]; // Paper int l = 0; - Iterator iterator1 = this.ar.iterator(); + Iterator iterator1 = chunkgenerator.getWorld().strongholdStuctures.iterator(); // Paper while (iterator1.hasNext()) { StructureStart structurestart = (StructureStart) iterator1.next(); - if (l < this.aq.length) { - this.aq[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.aq.length) { + if (l < strongholdCoords.length) { // Paper int j1 = 0; int k1 = 0; - for (int l1 = 0; l1 < this.aq.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.aq[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.aq.length - l1); + k = Math.min(k, strongholdCoords.length - l1); // Paper 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.l()).ar.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) } } }