From cbb2d459abba1d8349f806e65931ff3993276f64 Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Mon, 13 May 2024 09:12:59 -0500 Subject: [PATCH] Fix rare race condition --- .../impl/worldgen/OreFound.java | 7 +++-- .../impl/worldgen/OreGenMapSavedData.java | 30 ++++++++++++------- .../impl/worldgen/OreReplacer.java | 11 ++++--- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreFound.java b/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreFound.java index 01a1ba0..99a580f 100644 --- a/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreFound.java +++ b/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreFound.java @@ -2,17 +2,18 @@ import dev.lukebemish.excavatedvariants.api.data.Ore; import dev.lukebemish.excavatedvariants.api.data.Stone; +import org.jspecify.annotations.Nullable; public interface OreFound { - Ore excavated_variants$getOre(); + @Nullable Ore excavated_variants$getOre(); void excavated_variants$setOre(Ore o); - Stone excavated_variants$getOreStone(); + @Nullable Stone excavated_variants$getOreStone(); void excavated_variants$setOreStone(Stone o); - Stone excavated_variants$getStone(); + @Nullable Stone excavated_variants$getStone(); void excavated_variants$setStone(Stone stone); } diff --git a/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreGenMapSavedData.java b/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreGenMapSavedData.java index ecfefee..8341bff 100644 --- a/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreGenMapSavedData.java +++ b/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreGenMapSavedData.java @@ -16,9 +16,9 @@ import java.util.Set; public class OreGenMapSavedData extends SavedData { - public static final String DATA_KEY = ExcavatedVariants.MOD_ID + "_ore_replacement"; + private static final String DATA_KEY = ExcavatedVariants.MOD_ID + "_ore_replacement"; private final Object2IntMap edgeCount; - private final Set ranMap = Collections.synchronizedSet(new HashSet<>()); + private final Set ran = Collections.synchronizedSet(new HashSet<>()); public OreGenMapSavedData() { Object2IntMap edgeMap = new Object2IntOpenHashMap<>(); @@ -30,18 +30,26 @@ public int getEdgeCount(ChunkKey chunkPos) { return edgeCount.getInt(chunkPos); } + public void incrEdgeCount(ChunkKey chunkPos) { + edgeCount.put(chunkPos, edgeCount.getInt(chunkPos) + 1); + this.setDirty(); + } + public void setEdgeCount(ChunkKey chunkPos, int count) { + if (count == 9) { + edgeCount.removeInt(chunkPos); + } edgeCount.put(chunkPos, count); this.setDirty(); } public void chunkRan(ChunkKey chunkPos) { - ranMap.add(chunkPos); + ran.add(chunkPos); this.setDirty(); } public boolean didChunkRun(ChunkKey chunkPos) { - return ranMap.contains(chunkPos); + return ran.contains(chunkPos); } public record ChunkKey(int x, int z) {} @@ -58,7 +66,7 @@ private static OreGenMapSavedData load(CompoundTag tag, HolderLookup.Provider pr data.edgeCount.put(new ChunkKey(edge1[i], edge2[i]), edge3[i]); } for (int i = 0; i < ran1.length; i++) { - data.ranMap.add(new ChunkKey(ran1[i], ran2[i])); + data.ran.add(new ChunkKey(ran1[i], ran2[i])); } } return data; @@ -84,15 +92,15 @@ public CompoundTag save(@NonNull CompoundTag tag, HolderLookup.Provider provider ArrayList edge3 = new ArrayList<>(); ArrayList ran1 = new ArrayList<>(); ArrayList ran2 = new ArrayList<>(); - for (ChunkKey p : edgeCount.keySet()) { - edge1.add(p.x()); - edge2.add(p.z()); - edge3.add(edgeCount.getInt(p)); - } - for (ChunkKey p : ranMap) { + for (ChunkKey p : ran) { ran1.add(p.x()); ran2.add(p.z()); } + for (var e : edgeCount.object2IntEntrySet()) { + edge1.add(e.getKey().x()); + edge2.add(e.getKey().z()); + edge3.add(e.getIntValue()); + } tag.putIntArray("edge_1", edge1.stream().mapToInt(Integer::intValue).toArray()); tag.putIntArray("edge_2", edge2.stream().mapToInt(Integer::intValue).toArray()); tag.putIntArray("edge_3", edge3.stream().mapToInt(Integer::intValue).toArray()); diff --git a/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreReplacer.java b/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreReplacer.java index b82ba11..3b053d9 100644 --- a/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreReplacer.java +++ b/src/main/java/dev/lukebemish/excavatedvariants/impl/worldgen/OreReplacer.java @@ -14,7 +14,6 @@ import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; public class OreReplacer extends Feature { private static final int[] xs = new int[]{-1, 0, 1, 1, -1, -1, 0, 1}; @@ -43,8 +42,8 @@ public boolean modifyUnmodifiedNeighboringChunks(WorldGenLevel level, BlockPos p newPos.setX(pos.getX() + xs[i] * 16); newPos.setZ(pos.getZ() + zs[i] * 16); OreGenMapSavedData.ChunkKey chunkPos = new OreGenMapSavedData.ChunkKey(newPos.getX(), newPos.getZ()); - data.setEdgeCount(chunkPos, data.getEdgeCount(chunkPos) + 1); - if (data.getEdgeCount(chunkPos) == 8 && data.didChunkRun(chunkPos)) { + data.incrEdgeCount(chunkPos); + if (data.getEdgeCount(chunkPos) >= 8 && data.didChunkRun(chunkPos)) { ChunkAccess chunkAccess = level.getChunk(newPos); modifyChunk(chunkAccess, minY, maxY); data.setEdgeCount(chunkPos, 9); @@ -52,7 +51,7 @@ public boolean modifyUnmodifiedNeighboringChunks(WorldGenLevel level, BlockPos p } OreGenMapSavedData.ChunkKey chunkPos = new OreGenMapSavedData.ChunkKey(pos.getX(), pos.getZ()); data.chunkRan(chunkPos); - if (data.getEdgeCount(chunkPos) == 8) { + if (data.getEdgeCount(chunkPos) >= 8) { ChunkAccess chunkAccess = level.getChunk(pos); modifyChunk(chunkAccess, minY, maxY); data.setEdgeCount(chunkPos, 9); @@ -81,9 +80,9 @@ public void modifyChunk(ChunkAccess chunkAccess, int minY, int maxY) { if (cache[i][y & 15][j] == null) { cache[i][y & 15][j] = newState; } - @Nullable Ore ore = ((OreFound) newState.getBlock()).excavated_variants$getOre(); + Ore ore = ((OreFound) newState.getBlock()).excavated_variants$getOre(); if (ore != null) { - @Nullable Stone oreStone = ((OreFound) newState.getBlock()).excavated_variants$getOreStone(); + Stone oreStone = ((OreFound) newState.getBlock()).excavated_variants$getOreStone(); for (int c = 0; c < as.length; c++) { if (i + as[c] < 16 && i + as[c] >= 0 && j + bs[c] < 16 && j + bs[c] >= 0 && y + ys[c] >= SectionPos.sectionToBlockCoord(sectionIndex) && y + ys[c] < SectionPos.sectionToBlockCoord(sectionIndex + 1)) { BlockState thisState = cache[i + as[c]][y + ys[c] & 15][j + bs[c]];