From 8b1a0bbc344a5390800cbe1cdba8533ff76c12a4 Mon Sep 17 00:00:00 2001 From: IronApollo Date: Thu, 7 May 2020 12:29:18 -0400 Subject: [PATCH] Fix #417 This commit aims to fix existing issues regarding the "0/-1 blocks affected" bug. Introducing the new LinkedFilter class allows us to use multiple filters for single-filter operations, e.g. applying a pattern to blocks while also counting the amount of blocks applied to. SetFilter.java was also removed due to not being used. --- .../implementation/filter/LinkedFilter.java | 36 +++++++++++++++++++ .../implementation/filter}/MaskFilter.java | 19 +++++++++- .../beta/implementation/filter/SetFilter.java | 19 ---------- .../queue/ParallelQueueExtent.java | 32 +++++++---------- .../java/com/sk89q/worldedit/EditSession.java | 25 +++++++++++++ .../sk89q/worldedit/function/mask/Mask.java | 1 + 6 files changed, 93 insertions(+), 39 deletions(-) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/LinkedFilter.java rename worldedit-core/src/main/java/com/{sk89q/worldedit/function/mask => boydti/fawe/beta/implementation/filter}/MaskFilter.java (64%) delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/SetFilter.java diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/LinkedFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/LinkedFilter.java new file mode 100644 index 000000000..c749fa6e7 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/LinkedFilter.java @@ -0,0 +1,36 @@ +package com.boydti.fawe.beta.implementation.filter; + +import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.implementation.filter.block.DelegateFilter; +import com.boydti.fawe.beta.implementation.filter.block.FilterBlock; + +/** + * Filter which links two Filters together for single-filter-input operations. + * + * @param Parent which extends Filter + * @param Child which extends Filter + */ +public final class LinkedFilter extends DelegateFilter { + + private final S child; + + public LinkedFilter(T parent, S child){ + super(parent); + this.child = child; + } + + public S getChild(){ + return this.child; + } + + @Override + public void applyBlock(FilterBlock block) { + this.getParent().applyBlock(block); + this.getChild().applyBlock(block); + } + + @Override + public LinkedFilter, Filter> newInstance(Filter other) { + return new LinkedFilter<>(this, other); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/MaskFilter.java similarity index 64% rename from worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskFilter.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/MaskFilter.java index 850a80cc0..9aca5764f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskFilter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/MaskFilter.java @@ -1,14 +1,21 @@ -package com.sk89q.worldedit.function.mask; +package com.boydti.fawe.beta.implementation.filter; import com.boydti.fawe.beta.implementation.filter.block.DelegateFilter; import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.implementation.filter.block.FilterBlock; +import com.sk89q.worldedit.function.mask.Mask; import java.util.function.Supplier; +/** + * Filter with an attached Mask used for deciding whether a block is eligible for being applied to. + * + * @param Parent which extends Filter + */ public class MaskFilter extends DelegateFilter { private final Supplier supplier; private final Mask mask; + private int changes; public MaskFilter(T other, Mask mask) { this(other, () -> mask); @@ -28,9 +35,19 @@ public class MaskFilter extends DelegateFilter { public void applyBlock(FilterBlock block) { if (mask.test(block, block)) { getParent().applyBlock(block); + this.changes++; } } + /** + * Get the number of blocks which passed the Mask test and were applied to + * + * @return number of blocks which passed the Mask test and were applied to + */ + public int getBlocksApplied(){ + return this.changes; + } + @Override public MaskFilter newInstance(Filter other) { return new MaskFilter<>(other, supplier); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/SetFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/SetFilter.java deleted file mode 100644 index 153313469..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/filter/SetFilter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.boydti.fawe.beta.implementation.filter; - -import com.boydti.fawe.beta.Filter; -import com.boydti.fawe.beta.implementation.filter.block.FilterBlock; -import com.sk89q.worldedit.world.block.BlockState; - -public class SetFilter implements Filter { - - private final BlockState state; - - public SetFilter(BlockState state) { - this.state = state; - } - - @Override - public void applyBlock(FilterBlock block) { - block.setBlock(state); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java index 92caa5374..c93052360 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java @@ -1,13 +1,14 @@ package com.boydti.fawe.beta.implementation.queue; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.beta.IQueueChunk; -import com.boydti.fawe.beta.IQueueWrapper; -import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock; import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.IQueueChunk; import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.IQueueWrapper; import com.boydti.fawe.beta.implementation.filter.CountFilter; import com.boydti.fawe.beta.implementation.filter.DistrFilter; +import com.boydti.fawe.beta.implementation.filter.LinkedFilter; +import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock; import com.boydti.fawe.beta.implementation.processors.BatchProcessorHolder; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.clipboard.WorldCopyClipboard; @@ -16,6 +17,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.BlockMask; +import com.sk89q.worldedit.function.mask.BlockMaskBuilder; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.BlockPattern; @@ -36,13 +38,12 @@ import java.util.Set; import java.util.concurrent.ForkJoinTask; import java.util.stream.IntStream; -import static com.google.common.base.Preconditions.checkNotNull; - public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrapper { private final World world; private final QueueHandler handler; private final BatchProcessorHolder processor; + private int changes; public ParallelQueueExtent(QueueHandler handler, World world) { super(handler.getQueue(world, new BatchProcessorHolder())); @@ -52,8 +53,8 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap } @Override - public IQueueExtent getExtent() { - return (IQueueExtent) super.getExtent(); + public IQueueExtent getExtent() { + return (IQueueExtent) super.getExtent(); } @Override @@ -126,10 +127,6 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap return filter; } - public int getChanges() { - return -1; - } - @Override public int countBlocks(Region region, Mask searchMask) { return @@ -142,33 +139,30 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap @Override public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { - apply(region, block, true); - return getChanges(); + return this.changes = apply(region, new BlockMaskBuilder().add(block).build(this).toFilter(new CountFilter())).getParent().getTotal(); } @Override public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { - apply(region, pattern, true); - return getChanges(); + return this.changes = apply(region, new LinkedFilter<>(pattern, new CountFilter()), true).getChild().getTotal(); } @Override public int setBlocks(Set vset, Pattern pattern) { if (vset instanceof Region) { - setBlocks((Region) vset, pattern); + this.changes = setBlocks((Region) vset, pattern); } // TODO optimize parallel for (BlockVector3 blockVector3 : vset) { pattern.apply(this, blockVector3, blockVector3); } - return getChanges(); + return this.changes; } @Override public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { - apply(region, mask.toFilter(pattern), false); - return getChanges(); + return this.changes = apply(region, mask.toFilter(pattern), false).getBlocksApplied(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index a4622dbfc..4e594248e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -1069,6 +1069,31 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { return this.changes; } + @Override + public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { + return this.changes = super.setBlocks(region, block); + } + + @Override + public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { + return this.changes = super.setBlocks(region, pattern); + } + + @Override + public > int replaceBlocks(Region region, Set filter, B replacement) throws MaxChangedBlocksException { + return this.changes = super.replaceBlocks(region, filter, replacement); + } + + @Override + public int replaceBlocks(Region region, Set filter, Pattern pattern) throws MaxChangedBlocksException { + return this.changes = super.replaceBlocks(region, filter, pattern); + } + + @Override + public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { + return this.changes = super.replaceBlocks(region, mask, pattern); + } + /** * Fills an area recursively in the X/Z directions. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java index 33b1d1546..7267cb13c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.function.mask; import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.implementation.filter.MaskFilter; import com.boydti.fawe.beta.implementation.filter.block.FilterBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.NullExtent;