From 278e9d59911c66340124f68f7e9e4b3794b701e8 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sun, 10 Jan 2021 14:59:21 +0000 Subject: [PATCH] Set source masks that include the editsession's allowed regions to ForwardExtentCopies Fixes #710 --- .../boydti/fawe/util/EditSessionBuilder.java | 4 ++ .../java/com/sk89q/worldedit/EditSession.java | 35 ++++++++++++--- .../worldedit/command/ClipboardCommands.java | 44 ++++++++++++++----- .../function/mask/MaskIntersection.java | 2 +- .../worldedit/function/mask/RegionMask.java | 8 ++++ 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java index 8d8ad1f13..8ec1c03a4 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java @@ -457,4 +457,8 @@ public class EditSessionBuilder { return wnaMode; } + public Region[] getAllowedRegions() { + return allowedRegions; + } + } 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 4e6ae84e7..d142a182a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -109,7 +109,9 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.FlatRegion; +import com.sk89q.worldedit.regions.NullRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionIntersection; import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape; import com.sk89q.worldedit.regions.shape.ArbitraryShape; @@ -224,6 +226,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { private final boolean wnaMode; + @Nullable + private final Region[] allowedRegions; + @Deprecated public EditSession(@NotNull EventBus bus, World world, @Nullable Player player, @@ -260,6 +265,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { this.blockBag = builder.getBlockBag(); this.history = changeSet != null; this.wnaMode = builder.isWNAMode(); + this.allowedRegions = builder.getAllowedRegions().clone(); } /** @@ -307,8 +313,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } /** - * The region extent restricts block placements to allow max Y regions. - * TODO This doc needs to be rewritten because it may not actually describe what it does. + * Returns the RegionExtent that will restrict an edit, or null. * * @return FaweRegionExtent (may be null) */ @@ -483,6 +488,11 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { return maskingExtent != null ? maskingExtent.get().getMask() : null; } + @Nullable + public Region[] getAllowedRegions() { + return allowedRegions; + } + public void addTransform(ResettableExtent transform) { checkNotNull(transform); transform.setExtent(getExtent()); @@ -1530,7 +1540,13 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { copy.setTransform(new AffineTransform().translate(dir.multiply(size))); copy.setCopyingEntities(copyEntities); copy.setCopyingBiomes(copyBiomes); - mask = MaskIntersection.of(getSourceMask(), mask).optimize(); + final Region allowedRegion; + if (allowedRegions == null || allowedRegions.length == 0) { + allowedRegion = new NullRegion(); + } else { + allowedRegion = new RegionIntersection(allowedRegions); + } + mask = MaskIntersection.of(getSourceMask(), mask, new RegionMask(allowedRegion)).optimize(); if (mask != Masks.alwaysTrue()) { setSourceMask(null); copy.setSourceMask(mask); @@ -1605,14 +1621,19 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { copy.setRemovingEntities(moveEntities); copy.setCopyingBiomes(copyBiomes); copy.setRepetitions(1); - if (mask != null) { - new MaskTraverser(mask).reset(this); + final Region allowedRegion; + if (allowedRegions == null || allowedRegions.length == 0) { + allowedRegion = new NullRegion(); + } else { + allowedRegion = new RegionIntersection(allowedRegions); + } + mask = MaskIntersection.of(getSourceMask(), mask, new RegionMask(allowedRegion)).optimize(); + if (mask != Masks.alwaysTrue()) { copy.setSourceMask(mask); - if (this.getSourceMask() == mask) { + if (this.getSourceMask().equals(mask)) { setSourceMask(null); } } - Operations.completeBlindly(copy); return this.changes = copy.getAffected(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 468ded6b3..248cfe5a4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -55,6 +55,9 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.MaskIntersection; +import com.sk89q.worldedit.function.mask.Masks; +import com.sk89q.worldedit.function.mask.RegionMask; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operations; @@ -66,7 +69,9 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.Transform; +import com.sk89q.worldedit.regions.NullRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionIntersection; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.session.ClipboardHolder; @@ -140,14 +145,24 @@ public class ClipboardCommands { copy.setCopyingBiomes(copyBiomes); Mask sourceMask = editSession.getSourceMask(); + Region[] regions = editSession.getAllowedRegions(); + Region allowedRegion; + if (regions == null || regions.length == 0) { + allowedRegion = new NullRegion(); + } else { + allowedRegion = new RegionIntersection(regions); + } + final Mask firstSourceMask = mask != null ? mask : sourceMask; + final Mask finalMask = MaskIntersection.of(firstSourceMask, new RegionMask(allowedRegion)).optimize(); + if (finalMask != Masks.alwaysTrue()) { + copy.setSourceMask(finalMask); + } if (sourceMask != null) { + editSession.setSourceMask(null); new MaskTraverser(sourceMask).reset(editSession); - copy.setSourceMask(sourceMask); editSession.setSourceMask(null); } - if (mask != null) { - copy.setSourceMask(mask); - } + Operations.completeLegacy(copy); saveDiskClipboard(clipboard); session.setClipboard(new ClipboardHolder(clipboard)); @@ -252,13 +267,22 @@ public class ClipboardCommands { copy.setRemovingEntities(true); copy.setCopyingBiomes(copyBiomes); Mask sourceMask = editSession.getSourceMask(); - if (sourceMask != null) { - new MaskTraverser(sourceMask).reset(editSession); - copy.setSourceMask(sourceMask); - editSession.setSourceMask(null); + Region[] regions = editSession.getAllowedRegions(); + Region allowedRegion; + if (regions == null || regions.length == 0) { + allowedRegion = new NullRegion(); + } else { + allowedRegion = new RegionIntersection(regions); } - if (mask != null) { - copy.setSourceMask(mask); + final Mask firstSourceMask = mask != null ? mask : sourceMask; + final Mask finalMask = MaskIntersection.of(firstSourceMask, new RegionMask(allowedRegion)).optimize(); + if (finalMask != Masks.alwaysTrue()) { + copy.setSourceMask(finalMask); + } + if (sourceMask != null) { + editSession.setSourceMask(null); + new MaskTraverser(sourceMask).reset(editSession); + editSession.setSourceMask(null); } Operations.completeLegacy(copy); saveDiskClipboard(clipboard); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java index ab8b95b0b..6351653e7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java @@ -81,7 +81,7 @@ public class MaskIntersection extends AbstractMask { case 1: return set.iterator().next(); default: - return new MaskIntersection(masks).optimize(); + return new MaskIntersection(set).optimize(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/RegionMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/RegionMask.java index d20e7cd64..ab7641a1d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/RegionMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/RegionMask.java @@ -77,4 +77,12 @@ public class RegionMask extends AbstractMask { return new RegionMask(region.clone()); } + @Override + public Mask optimize() { + if (region.isGlobal()) { + return Masks.alwaysTrue(); + } + return this; + } + }