From f4da4b0287d431b30cf39f77cf6089683bb38d32 Mon Sep 17 00:00:00 2001 From: Jordan Date: Sat, 15 Jul 2023 16:40:29 +0100 Subject: [PATCH] fix: fix adding/getting masks to/from MaskExtent when it is a processor (#2351) - fixes #2350 --- .../core/util/ProcessorTraverser.java | 44 +++++++++++++++++++ .../java/com/sk89q/worldedit/EditSession.java | 32 ++++++++++---- 2 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ProcessorTraverser.java diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ProcessorTraverser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ProcessorTraverser.java new file mode 100644 index 000000000..3c3a601a1 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/ProcessorTraverser.java @@ -0,0 +1,44 @@ +package com.fastasyncworldedit.core.util; + +import com.fastasyncworldedit.core.extent.processor.BatchProcessorHolder; +import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor; +import com.fastasyncworldedit.core.queue.IBatchProcessor; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import org.apache.logging.log4j.Logger; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayDeque; +import java.util.Queue; + +public class ProcessorTraverser { + + private static final Logger LOGGER = LogManagerCompat.getLogger(); + + private final T root; + + public ProcessorTraverser(@Nonnull T root) { + this.root = root; + } + + public @Nullable U find(Class clazz) { + try { + Queue processors = new ArrayDeque<>(); + IBatchProcessor processor = root; + do { + if (clazz.isAssignableFrom(processor.getClass())) { + return clazz.cast(processor); + } else if (processor instanceof MultiBatchProcessor multiProcessor) { + processors.addAll(multiProcessor.getBatchProcessors()); + } else if (processor instanceof BatchProcessorHolder holder) { + processors.add(holder.getProcessor()); + } + } while ((processor = processors.poll()) != null); + return null; + } catch (Throwable e) { + LOGGER.error("Error traversing processors", e); + return null; + } + } + +} 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 780ba90e1..03b838de6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -30,6 +30,7 @@ import com.fastasyncworldedit.core.extent.ResettableExtent; import com.fastasyncworldedit.core.extent.SingleRegionExtent; import com.fastasyncworldedit.core.extent.SourceMaskExtent; import com.fastasyncworldedit.core.extent.clipboard.WorldCopyClipboard; +import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder; import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter; import com.fastasyncworldedit.core.extent.processor.lighting.Relighter; import com.fastasyncworldedit.core.function.SurfaceRegionFunction; @@ -55,6 +56,7 @@ import com.fastasyncworldedit.core.queue.implementation.preloader.Preloader; import com.fastasyncworldedit.core.util.ExtentTraverser; import com.fastasyncworldedit.core.util.MaskTraverser; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.ProcessorTraverser; import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.collection.BlockVector3Set; import com.fastasyncworldedit.core.util.task.RunnableVal; @@ -524,9 +526,15 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @return mask, may be null */ public Mask getMask() { - //FAWE start - ExtendTraverser & MaskingExtents - ExtentTraverser maskingExtent = new ExtentTraverser<>(getExtent()).find(MaskingExtent.class); - return maskingExtent != null ? maskingExtent.get().getMask() : null; + //FAWE start - ExtentTraverser & MaskingExtents + MaskingExtent maskingExtent = new ExtentTraverser<>(getExtent()).findAndGet(MaskingExtent.class); + if (maskingExtent == null) { + ExtentTraverser processorExtent = + new ExtentTraverser<>(getExtent()).find(ExtentBatchProcessorHolder.class); + maskingExtent = + new ProcessorTraverser<>(processorExtent.get().getProcessor()).find(MaskingExtent.class); + } + return maskingExtent != null ? maskingExtent.getMask() : null; //FAWE end } @@ -609,23 +617,29 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { //FAWE start - use MaskingExtent & ExtentTraverser /** - * Set a mask. + * Set a mask. Combines with any existing masks, set null to clear existing masks. * * @param mask mask or null */ - public void setMask(Mask mask) { + public void setMask(@Nullable Mask mask) { if (mask == null) { mask = Masks.alwaysTrue(); } else { new MaskTraverser(mask).reset(this); } - ExtentTraverser maskingExtent = new ExtentTraverser<>(getExtent()).find(MaskingExtent.class); - if (maskingExtent != null && maskingExtent.get() != null) { - Mask oldMask = maskingExtent.get().getMask(); + MaskingExtent maskingExtent = new ExtentTraverser<>(getExtent()).findAndGet(MaskingExtent.class); + if (maskingExtent == null && mask != Masks.alwaysTrue()) { + ExtentTraverser processorExtent = + new ExtentTraverser<>(getExtent()).find(ExtentBatchProcessorHolder.class); + maskingExtent = + new ProcessorTraverser<>(processorExtent.get().getProcessor()).find(MaskingExtent.class); + } + if (maskingExtent != null) { + Mask oldMask = maskingExtent.getMask(); if (oldMask instanceof ResettableMask) { ((ResettableMask) oldMask).reset(); } - maskingExtent.get().setMask(mask); + maskingExtent.setMask(mask); } else if (mask != Masks.alwaysTrue()) { addProcessor(new MaskingExtent(getExtent(), mask)); }