From 61bc012f6fc78fd34b652d6fbd6032653daeee95 Mon Sep 17 00:00:00 2001 From: wizjany Date: Sat, 10 Aug 2019 11:54:22 -0400 Subject: [PATCH] Fix source masks using EditSession instead of clipboard. (#515) --- .../worldedit/command/BrushCommands.java | 7 +++- .../worldedit/command/ClipboardCommands.java | 2 + .../command/argument/FactoryConverter.java | 42 +++++++++++++++++-- .../factory/parser/mask/BiomeMaskParser.java | 3 +- .../parser/mask/BlockCategoryMaskParser.java | 3 +- .../parser/mask/BlockStateMaskParser.java | 3 +- .../factory/parser/mask/BlocksMaskParser.java | 3 +- .../parser/mask/ExistingMaskParser.java | 3 +- .../parser/mask/ExpressionMaskParser.java | 3 +- .../factory/parser/mask/OffsetMaskParser.java | 3 +- .../factory/parser/mask/SolidMaskParser.java | 3 +- .../internal/annotation/ClipboardMask.java | 37 ++++++++++++++++ 12 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/ClipboardMask.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 25f198e92..9b8e35dae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -48,6 +48,7 @@ import com.sk89q.worldedit.function.mask.BlockTypeMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.annotation.ClipboardMask; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.session.ClipboardHolder; @@ -156,9 +157,13 @@ public class BrushCommands { @Switch(name = 'b', desc = "Paste biomes if available") boolean pasteBiomes, @ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "") + @ClipboardMask Mask sourceMask) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); + Clipboard clipboard = holder.getClipboard(); + ClipboardHolder newHolder = new ClipboardHolder(clipboard); + newHolder.setTransform(holder.getTransform()); BlockVector3 size = clipboard.getDimensions(); @@ -167,7 +172,7 @@ public class BrushCommands { worldEdit.checkMaxBrushRadius(size.getBlockZ() / 2D - 1); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); - tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin, pasteEntities, pasteBiomes, sourceMask), "worldedit.brush.clipboard"); + tool.setBrush(new ClipboardBrush(newHolder, ignoreAir, usingOrigin, pasteEntities, pasteBiomes, sourceMask), "worldedit.brush.clipboard"); player.print("Clipboard brush shape equipped."); } 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 d2b9f7747..70bbd29de 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 @@ -35,6 +35,7 @@ import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.annotation.ClipboardMask; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.math.BlockVector3; @@ -143,6 +144,7 @@ public class ClipboardCommands { @Switch(name = 'b', desc = "Paste biomes if available") boolean pasteBiomes, @ArgFlag(name = 'm', desc = "Only paste blocks matching this mask", def = "") + @ClipboardMask Mask sourceMask) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java index d6259abf3..8b5a56f0c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.command.argument; +import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseItem; @@ -27,9 +28,14 @@ import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.transform.BlockTransformExtent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.annotation.ClipboardMask; import com.sk89q.worldedit.internal.registry.AbstractFactory; +import com.sk89q.worldedit.math.transform.Transform; +import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.session.request.RequestExtent; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.World; @@ -41,30 +47,53 @@ import org.enginehub.piston.converter.SuccessfulConversion; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; +import javax.annotation.Nullable; import java.util.List; +import java.util.function.Consumer; import java.util.function.Function; public class FactoryConverter implements ArgumentConverter { public static void register(WorldEdit worldEdit, CommandManager commandManager) { commandManager.registerConverter(Key.of(Pattern.class), - new FactoryConverter<>(worldEdit, WorldEdit::getPatternFactory, "pattern")); + new FactoryConverter<>(worldEdit, WorldEdit::getPatternFactory, "pattern", null)); commandManager.registerConverter(Key.of(Mask.class), - new FactoryConverter<>(worldEdit, WorldEdit::getMaskFactory, "mask")); + new FactoryConverter<>(worldEdit, WorldEdit::getMaskFactory, "mask", null)); commandManager.registerConverter(Key.of(BaseItem.class), - new FactoryConverter<>(worldEdit, WorldEdit::getItemFactory, "item")); + new FactoryConverter<>(worldEdit, WorldEdit::getItemFactory, "item", null)); + + commandManager.registerConverter(Key.of(Mask.class, ClipboardMask.class), + new FactoryConverter<>(worldEdit, WorldEdit::getMaskFactory, "mask", + context -> { + try { + ClipboardHolder holder = context.getSession().getClipboard(); + Transform transform = holder.getTransform(); + Extent target; + if (transform.isIdentity()) { + target = holder.getClipboard(); + } else { + target = new BlockTransformExtent(holder.getClipboard(), transform); + } + context.setExtent(target); + } catch (EmptyClipboardException e) { + throw new IllegalStateException(e); + } + })); } private final WorldEdit worldEdit; private final Function> factoryExtractor; private final String description; + @Nullable private final Consumer contextTweaker; private FactoryConverter(WorldEdit worldEdit, Function> factoryExtractor, - String description) { + String description, + @Nullable Consumer contextTweaker) { this.worldEdit = worldEdit; this.factoryExtractor = factoryExtractor; this.description = description; + this.contextTweaker = contextTweaker; } @Override @@ -80,10 +109,15 @@ public class FactoryConverter implements ArgumentConverter { if (extent instanceof World) { parserContext.setWorld((World) extent); } + parserContext.setExtent(new RequestExtent()); } parserContext.setSession(session); parserContext.setRestricted(true); + if (contextTweaker != null) { + contextTweaker.accept(parserContext); + } + try { return SuccessfulConversion.fromSingle( factoryExtractor.apply(worldEdit).parseFromInput(argument, parserContext) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BiomeMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BiomeMaskParser.java index 9e38e2e82..b578fd031 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BiomeMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BiomeMaskParser.java @@ -28,7 +28,6 @@ import com.sk89q.worldedit.function.mask.BiomeMask2D; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.internal.registry.InputParser; -import com.sk89q.worldedit.session.request.RequestExtent; import com.sk89q.worldedit.world.biome.BiomeType; import java.util.Arrays; @@ -78,6 +77,6 @@ public class BiomeMaskParser extends InputParser { biomes.add(biome); } - return Masks.asMask(new BiomeMask2D(new RequestExtent(), biomes)); + return Masks.asMask(new BiomeMask2D(context.getExtent(), biomes)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockCategoryMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockCategoryMaskParser.java index ee7bebf44..5fa9033b2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockCategoryMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockCategoryMaskParser.java @@ -26,7 +26,6 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.BlockCategoryMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.registry.InputParser; -import com.sk89q.worldedit.session.request.RequestExtent; import com.sk89q.worldedit.world.block.BlockCategory; import java.util.Locale; @@ -54,7 +53,7 @@ public class BlockCategoryMaskParser extends InputParser { if (category == null) { throw new InputParseException("Unrecognised tag '" + input.substring(2) + '\''); } else { - return new BlockCategoryMask(new RequestExtent(), category); + return new BlockCategoryMask(context.getExtent(), category); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockStateMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockStateMaskParser.java index 95884b821..ca47294b4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockStateMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlockStateMaskParser.java @@ -26,7 +26,6 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.BlockStateMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.registry.InputParser; -import com.sk89q.worldedit.session.request.RequestExtent; import java.util.stream.Stream; @@ -53,7 +52,7 @@ public class BlockStateMaskParser extends InputParser { boolean strict = input.charAt(1) == '='; String states = input.substring(2 + (strict ? 1 : 0), input.length() - 1); try { - return new BlockStateMask(new RequestExtent(), + return new BlockStateMask(context.getExtent(), Splitter.on(',').omitEmptyStrings().trimResults().withKeyValueSeparator('=').split(states), strict); } catch (Exception e) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java index 8580eb8a1..c4208dd94 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/BlocksMaskParser.java @@ -26,7 +26,6 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.registry.InputParser; -import com.sk89q.worldedit.session.request.RequestExtent; import com.sk89q.worldedit.world.block.BaseBlock; import java.util.Set; @@ -56,7 +55,7 @@ public class BlocksMaskParser extends InputParser { if (holders.isEmpty()) { return null; } - return new BlockMask(new RequestExtent(), holders); + return new BlockMask(context.getExtent(), holders); } catch (NoMatchException e) { return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExistingMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExistingMaskParser.java index 21feb6449..1f55824ae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExistingMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExistingMaskParser.java @@ -25,7 +25,6 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.registry.SimpleInputParser; -import com.sk89q.worldedit.session.request.RequestExtent; import java.util.List; @@ -44,6 +43,6 @@ public class ExistingMaskParser extends SimpleInputParser { @Override public Mask parseFromSimpleInput(String input, ParserContext context) { - return new ExistingBlockMask(new RequestExtent()); + return new ExistingBlockMask(context.getExtent()); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java index ac104e198..7438e2759 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java @@ -30,7 +30,6 @@ import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.session.SessionOwner; -import com.sk89q.worldedit.session.request.RequestExtent; import java.util.function.IntSupplier; import java.util.stream.Stream; @@ -58,7 +57,7 @@ public class ExpressionMaskParser extends InputParser { try { Expression exp = Expression.compile(input.substring(1), "x", "y", "z"); WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment( - new RequestExtent(), Vector3.ONE, Vector3.ZERO); + context.getExtent(), Vector3.ONE, Vector3.ZERO); exp.setEnvironment(env); if (context.getActor() != null) { SessionOwner owner = context.getActor(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/OffsetMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/OffsetMaskParser.java index ede9b6c79..b6c222f2e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/OffsetMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/OffsetMaskParser.java @@ -29,7 +29,6 @@ import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.mask.OffsetMask; import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.session.request.RequestExtent; import java.util.stream.Stream; @@ -62,7 +61,7 @@ public class OffsetMaskParser extends InputParser { if (input.length() > 1) { submask = worldEdit.getMaskFactory().parseFromInput(input.substring(1), context); } else { - submask = new ExistingBlockMask(new RequestExtent()); + submask = new ExistingBlockMask(context.getExtent()); } OffsetMask offsetMask = new OffsetMask(submask, BlockVector3.at(0, firstChar == '>' ? -1 : 1, 0)); return new MaskIntersection(offsetMask, Masks.negate(submask)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SolidMaskParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SolidMaskParser.java index f5ae3244a..412240a64 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SolidMaskParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/SolidMaskParser.java @@ -25,7 +25,6 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.internal.registry.SimpleInputParser; -import com.sk89q.worldedit.session.request.RequestExtent; import java.util.List; @@ -44,6 +43,6 @@ public class SolidMaskParser extends SimpleInputParser { @Override public Mask parseFromSimpleInput(String input, ParserContext context) { - return new SolidBlockMask(new RequestExtent()); + return new SolidBlockMask(context.getExtent()); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/ClipboardMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/ClipboardMask.java new file mode 100644 index 000000000..6b8be85e0 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/ClipboardMask.java @@ -0,0 +1,37 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.internal.annotation; + +import com.sk89q.worldedit.function.mask.Mask; +import org.enginehub.piston.inject.InjectAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a {@link Mask} parameter to use the clipboard as the extent instead of target World/EditSession. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +@InjectAnnotation +public @interface ClipboardMask { +}