From eaeb3a633aa3a42c0824da33fe77fc995427c52d Mon Sep 17 00:00:00 2001 From: Jordan Date: Wed, 19 Jun 2024 07:38:33 +0200 Subject: [PATCH] fix: always init ChunkFilterBlock to the chunk (#2788) - rename initFilterBlock from init to create - remove where we now needlessly init filter blocks - fixes #2662 --- .../core/queue/IQueueExtent.java | 14 +++++++++++--- .../queue/implementation/ParallelQueueExtent.java | 7 +++++-- .../implementation/SingleThreadQueueExtent.java | 2 +- .../core/regions/PolyhedralRegion.java | 2 +- .../fastasyncworldedit/core/regions/Triangle.java | 14 +++++++++++++- .../com/sk89q/worldedit/extent/MaskingExtent.java | 3 ++- .../com/sk89q/worldedit/regions/CuboidRegion.java | 1 - .../sk89q/worldedit/regions/EllipsoidRegion.java | 2 -- .../java/com/sk89q/worldedit/regions/Region.java | 1 - 9 files changed, 33 insertions(+), 13 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java index c13373d9a..3f104b35d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java @@ -115,7 +115,7 @@ public interface IQueueExtent extends Flushable, Trimable, ICh * A filter block is used to iterate over blocks / positions. Essentially combines BlockVector3, * Extent and BlockState functions in a way that avoids lookups. */ - ChunkFilterBlock initFilterBlock(); + ChunkFilterBlock createFilterBlock(); /** * Returns the number of chunks in this queue. @@ -129,7 +129,14 @@ public interface IQueueExtent extends Flushable, Trimable, ICh */ boolean isEmpty(); - default ChunkFilterBlock apply(ChunkFilterBlock block, Filter filter, Region region, int chunkX, int chunkZ, boolean full) { + default ChunkFilterBlock apply( + @Nullable ChunkFilterBlock block, + Filter filter, + Region region, + int chunkX, + int chunkZ, + boolean full + ) { if (!filter.appliesChunk(chunkX, chunkZ)) { return block; } @@ -139,8 +146,9 @@ public interface IQueueExtent extends Flushable, Trimable, ICh if (newChunk != null) { chunk = newChunk; if (block == null) { - block = this.initFilterBlock(); + block = this.createFilterBlock(); } + block.initChunk(chunkX, chunkZ); chunk.filterBlocks(filter, block, region, full); } this.submit(chunk); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java index 38546ed1b..1b56afdbc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.world.World; @@ -133,14 +134,16 @@ public class ParallelQueueExtent extends PassthroughExtent { final int size = Math.min(chunks.size(), Settings.settings().QUEUE.PARALLEL_THREADS); if (size <= 1) { // if PQE is ever used with PARALLEL_THREADS = 1, or only one chunk is edited, just run sequentially + ChunkFilterBlock block = null; while (chunksIter.hasNext()) { BlockVector2 pos = chunksIter.next(); - getExtent().apply(null, filter, region, pos.x(), pos.z(), full); + block = getExtent().apply(block, filter, region, pos.x(), pos.z(), full); } } else { final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> { try { final Filter newFilter = filter.fork(); + final Region newRegion = region.clone(); // Create a chunk that we will reuse/reset for each operation final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue(); queue.setFastMode(fastmode); @@ -162,7 +165,7 @@ public class ParallelQueueExtent extends PassthroughExtent { chunkX = pos.x(); chunkZ = pos.z(); } - block = queue.apply(block, newFilter, region, chunkX, chunkZ, full); + block = queue.apply(block, newFilter, newRegion, chunkX, chunkZ, full); } queue.flush(); } catch (Throwable t) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java index 789547d83..b0239a5a3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java @@ -473,7 +473,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen } @Override - public ChunkFilterBlock initFilterBlock() { + public ChunkFilterBlock createFilterBlock() { return new CharFilterBlock(this); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java index dbfe840c8..a1471c9d8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/PolyhedralRegion.java @@ -71,7 +71,7 @@ public class PolyhedralRegion extends AbstractRegion { public PolyhedralRegion(PolyhedralRegion region) { this(region.world); vertices.addAll(region.vertices); - triangles.addAll(region.triangles); + region.triangles.forEach(triangle -> triangles.add(triangle.clone())); vertexBacklog.addAll(region.vertexBacklog); minimumPoint = region.minimumPoint; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java index 2bb9fc5ac..1d96d5f95 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/regions/Triangle.java @@ -7,10 +7,14 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.polyhedron.Edge; -public class Triangle { +public class Triangle implements Cloneable { public static double RADIUS = 0.5; + private final BlockVector3 pos1; + private final BlockVector3 pos2; + private final BlockVector3 pos3; + private final double[][] verts = new double[3][3]; private final double[] center = new double[3]; private final double[] radius = new double[3]; @@ -28,6 +32,9 @@ public class Triangle { private final double b; public Triangle(BlockVector3 pos1, BlockVector3 pos2, BlockVector3 pos3) { + this.pos1 = pos1; + this.pos2 = pos2; + this.pos3 = pos3; verts[0] = new double[]{pos1.x(), pos1.y(), pos1.z()}; verts[1] = new double[]{pos2.x(), pos2.y(), pos2.z()}; verts[2] = new double[]{pos3.x(), pos3.y(), pos3.z()}; @@ -290,4 +297,9 @@ public class Triangle { return dot(normal, vmax) >= 0.0f; } + @Override + public Triangle clone() { + return new Triangle(pos1, pos2, pos3); + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java index 64b6eecc3..0abc80153 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java @@ -106,7 +106,8 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce @Override public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { final ChunkFilterBlock filter = getOrCreateFilterBlock.apply(Thread.currentThread().getId()); - return filter.filter(chunk, get, set, MaskingExtent.this); + filter.initChunk(chunk.getX(), chunk.getZ()); + return filter.filter(chunk, get, set, this); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java index 8e4da9214..4b0894d91 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java @@ -755,7 +755,6 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { ) { int chunkX = chunk.getX(); int chunkZ = chunk.getZ(); - block = block.initChunk(chunkX, chunkZ); //Chunk entry is an "interior chunk" in regards to the entire region, so filter the chunk whole instead of partially if ((minX + 15) >> 4 <= chunkX && (maxX - 15) >> 4 >= chunkX && (minZ + 15) >> 4 <= chunkZ && (maxZ - 15) >> 4 >= chunkZ) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java index 944e7a14c..1bc13ed43 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/EllipsoidRegion.java @@ -412,8 +412,6 @@ public class EllipsoidRegion extends AbstractRegion { return; } - block = block.initChunk(chunk.getX(), chunk.getZ()); - // Get the solid layers int cy = center.y(); int diffYFull = MathMan.usqrt(diffY2); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java index e8c6da179..08f2ee00c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java @@ -268,7 +268,6 @@ public interface Region extends Iterable, Cloneable, IBatchProcess ) { int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4); int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4); - block = block.initChunk(chunk.getX(), chunk.getZ()); for (int layer = minSection; layer <= maxSection; layer++) { if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { return;