diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java index 3a27fd634e..ab48332468 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.command.factory.ClipboardPasteFactory; import com.sk89q.worldedit.command.factory.ItemUseFactory; import com.sk89q.worldedit.command.factory.ReplaceFactory; import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; @@ -34,10 +35,13 @@ import com.sk89q.worldedit.function.Contextual; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.factory.ApplyRegion; +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.annotation.Direction; import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.regions.factory.RegionFactory; +import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.util.formatting.text.format.TextDecoration; @@ -48,6 +52,8 @@ import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.ArgFlag; +import org.enginehub.piston.annotation.param.Switch; import org.enginehub.piston.inject.Key; import org.enginehub.piston.part.CommandArgument; import org.enginehub.piston.part.SubCommandPart; @@ -100,6 +106,38 @@ private void setApplyBrush(CommandParameters parameters, Player player, LocalSes new ApplyRegion(generatorFactory), regionFactory, "worldedit.brush.apply"); } + @Command( + name = "clipboard", + desc = "Paste the clipboard at every block" + ) + @CommandPermissions("worldedit.brush.clipboard") + public void clipboard(CommandParameters parameters, Player player, LocalSession localSession, + @Switch(name = 'a', desc = "Don't paste air from the clipboard") + boolean ignoreAir, + @Switch(name = 'v', desc = "Include structure void blocks") + boolean pasteStructureVoid, + @Switch(name = 'o', desc = "Paste starting at each block, instead of centering on it") + boolean usingOrigin, + @Switch(name = 'e', desc = "Paste entities if available") + boolean pasteEntities, + @Switch(name = 'b', desc = "Paste biomes if available") + boolean pasteBiomes, + @ArgFlag(name = 'm', desc = "Only paste clipboard blocks matching this mask") + @ClipboardMask + Mask sourceMask) throws WorldEditException { + ClipboardHolder holder = localSession.getClipboard(); + + setApplyBrush(parameters, player, localSession, new ClipboardPasteFactory( + holder, + ignoreAir, + !pasteStructureVoid, + usingOrigin, + pasteEntities, + pasteBiomes, + sourceMask + )); + } + @Command( name = "forest", desc = "Plant trees" diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyCommands.java index 1b6bb9f78b..f27c0f1e78 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyCommands.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.command.factory.ClipboardPasteFactory; import com.sk89q.worldedit.command.factory.ItemUseFactory; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; @@ -38,6 +39,7 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.visitor.RegionVisitor; +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.internal.command.CommandRegistrationHandler; @@ -52,6 +54,8 @@ import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.ArgFlag; +import org.enginehub.piston.annotation.param.Switch; import org.enginehub.piston.inject.Key; import org.enginehub.piston.part.ArgAcceptingCommandFlag; import org.enginehub.piston.part.SubCommandPart; @@ -114,6 +118,38 @@ private int apply(CommandParameters parameters, Actor actor, EditSession editSes return visitor.getAffected(); } + @Command( + name = "clipboard", + desc = "Paste the clipboard at every block" + ) + @CommandPermissions("worldedit.clipboard.paste") + @Logging(REGION) + public int clipboard(CommandParameters parameters, Actor actor, EditSession editSession, + LocalSession localSession, @Selection Region region, + @Switch(name = 'a', desc = "Don't paste air from the clipboard") + boolean ignoreAir, + @Switch(name = 'v', desc = "Include structure void blocks") + boolean pasteStructureVoid, + @Switch(name = 'o', desc = "Paste starting at each block, instead of centering on it") + boolean usingOrigin, + @Switch(name = 'e', desc = "Paste entities if available") + boolean pasteEntities, + @Switch(name = 'b', desc = "Paste biomes if available") + boolean pasteBiomes, + @ArgFlag(name = 'm', desc = "Only paste clipboard blocks matching this mask") + @ClipboardMask + Mask sourceMask) throws WorldEditException { + return apply(parameters, actor, editSession, localSession, region, new ClipboardPasteFactory( + localSession.getClipboard(), + ignoreAir, + !pasteStructureVoid, + usingOrigin, + pasteEntities, + pasteBiomes, + sourceMask + )); + } + @Command( name = "item", desc = "Use an item" diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ClipboardPasteFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ClipboardPasteFactory.java new file mode 100644 index 0000000000..a557a47424 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ClipboardPasteFactory.java @@ -0,0 +1,70 @@ +/* + * 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.factory; + +import com.sk89q.worldedit.function.ClipboardPaste; +import com.sk89q.worldedit.function.Contextual; +import com.sk89q.worldedit.function.EditContext; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.session.ClipboardHolder; + +public final class ClipboardPasteFactory implements Contextual { + + private final ClipboardHolder holder; + private final boolean ignoreAirBlocks; + private final boolean ignoreStructureVoidBlocks; + private final boolean usingOrigin; + private final boolean pasteEntities; + private final boolean pasteBiomes; + private final Mask sourceMask; + + public ClipboardPasteFactory(ClipboardHolder holder, boolean ignoreAirBlocks, + boolean ignoreStructureVoidBlocks, boolean usingOrigin, + boolean pasteEntities, boolean pasteBiomes, Mask sourceMask) { + this.holder = new ClipboardHolder(holder.getClipboard()); + this.holder.setTransform(holder.getTransform()); + this.ignoreAirBlocks = ignoreAirBlocks; + this.ignoreStructureVoidBlocks = ignoreStructureVoidBlocks; + this.usingOrigin = usingOrigin; + this.pasteEntities = pasteEntities; + this.pasteBiomes = pasteBiomes; + this.sourceMask = sourceMask; + } + + @Override + public RegionFunction createFromContext(EditContext context) { + return new ClipboardPaste( + context.getDestination(), + holder, + ignoreAirBlocks, + ignoreStructureVoidBlocks, + usingOrigin, + pasteEntities, + pasteBiomes, + sourceMask + ); + } + + @Override + public String toString() { + return "paste clipboard"; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java index 9141b9ca55..c259343c52 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java @@ -22,13 +22,10 @@ import com.google.errorprone.annotations.InlineMe; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.function.ClipboardPaste; import com.sk89q.worldedit.function.mask.Mask; -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.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; public class ClipboardBrush implements Brush { @@ -65,21 +62,16 @@ public ClipboardBrush(ClipboardHolder holder, boolean ignoreAirBlocks, boolean i @Override public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { - Clipboard clipboard = holder.getClipboard(); - Region region = clipboard.getRegion(); - BlockVector3 centerOffset = region.getCenter().toBlockPoint().subtract(clipboard.getOrigin()); - - Operation operation = holder - .createPaste(editSession) - .to(usingOrigin ? position : position.subtract(centerOffset)) - .ignoreAirBlocks(ignoreAirBlocks) - .ignoreStructureVoidBlocks(ignoreStructureVoidBlocks) - .copyEntities(pasteEntities) - .copyBiomes(pasteBiomes) - .maskSource(sourceMask) - .build(); - - Operations.completeLegacy(operation); + new ClipboardPaste( + editSession, + holder, + ignoreAirBlocks, + ignoreStructureVoidBlocks, + usingOrigin, + pasteEntities, + pasteBiomes, + sourceMask + ).apply(position); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/ClipboardPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ClipboardPaste.java new file mode 100644 index 0000000000..c2a17202e5 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ClipboardPaste.java @@ -0,0 +1,76 @@ +/* + * 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.function; + +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.operation.ForwardExtentCopy; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.session.ClipboardHolder; + +public final class ClipboardPaste implements RegionFunction { + + private final Extent destination; + private final ClipboardHolder holder; + private final boolean ignoreAirBlocks; + private final boolean ignoreStructureVoidBlocks; + private final boolean usingOrigin; + private final boolean pasteEntities; + private final boolean pasteBiomes; + private final Mask sourceMask; + + public ClipboardPaste(Extent destination, ClipboardHolder holder, boolean ignoreAirBlocks, + boolean ignoreStructureVoidBlocks, boolean usingOrigin, boolean pasteEntities, + boolean pasteBiomes, Mask sourceMask) { + this.destination = destination; + this.holder = holder; + this.ignoreAirBlocks = ignoreAirBlocks; + this.ignoreStructureVoidBlocks = ignoreStructureVoidBlocks; + this.usingOrigin = usingOrigin; + this.pasteEntities = pasteEntities; + this.pasteBiomes = pasteBiomes; + this.sourceMask = sourceMask; + } + + @Override + public boolean apply(BlockVector3 position) throws MaxChangedBlocksException { + Clipboard clipboard = holder.getClipboard(); + Region region = clipboard.getRegion(); + BlockVector3 centerOffset = region.getCenter().toBlockPoint().subtract(clipboard.getOrigin()); + BlockVector3 transformedCenterOffset = holder.getTransform().apply(centerOffset.toVector3()).toBlockPoint(); + + ForwardExtentCopy operation = (ForwardExtentCopy) holder + .createPaste(destination) + .to(usingOrigin ? position : position.subtract(transformedCenterOffset)) + .ignoreAirBlocks(ignoreAirBlocks) + .ignoreStructureVoidBlocks(ignoreStructureVoidBlocks) + .copyEntities(pasteEntities) + .copyBiomes(pasteBiomes) + .maskSource(sourceMask) + .build(); + + Operations.completeLegacy(operation); + return operation.getAffected() > 0; + } +}