Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-07 20:10:06 +01:00
Allow copy/pasting biomes.
Copy takes a -b flag to copy biomes. Paste takes a -b flag to paste biomes (if available). This allows flexibility to create/load schematics with/without biomes (when schematic biome support is added). Also added a -m mask flag to paste to set a source mask, and a -e flag to skip pasting entities if they are loaded.
Dieser Commit ist enthalten in:
Ursprung
26511bcc25
Commit
af1af43ac1
@ -48,6 +48,7 @@ import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.session.PasteBuilder;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
@ -75,19 +76,21 @@ public class ClipboardCommands {
|
||||
help = "Copy the selection to the clipboard\n" +
|
||||
"Flags:\n" +
|
||||
" -e will also copy entities\n" +
|
||||
" -m sets a source mask so that excluded blocks become air",
|
||||
" -m sets a source mask so that excluded blocks become air\n" +
|
||||
" -b will also copy biomes",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.copy")
|
||||
public void copy(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region, @Switch('e') boolean copyEntities,
|
||||
@Switch('m') Mask mask) throws WorldEditException {
|
||||
@Switch('m') Mask mask, @Switch('b') boolean copyBiomes) throws WorldEditException {
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(session.getPlacementPosition(player));
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
|
||||
copy.setCopyingEntities(copyEntities);
|
||||
copy.setCopyingBiomes(copyBiomes);
|
||||
if (mask != null) {
|
||||
copy.setSourceMask(mask);
|
||||
}
|
||||
@ -121,6 +124,8 @@ public class ClipboardCommands {
|
||||
copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
|
||||
copy.setCopyingEntities(copyEntities);
|
||||
copy.setRemovingEntities(true);
|
||||
// doesn't really make sense to "cut" biomes? so copy anyway and let them choose when pasting
|
||||
copy.setCopyingBiomes(true);
|
||||
if (mask != null) {
|
||||
copy.setSourceMask(mask);
|
||||
}
|
||||
@ -133,14 +138,17 @@ public class ClipboardCommands {
|
||||
@Command(
|
||||
aliases = { "/paste" },
|
||||
usage = "",
|
||||
flags = "sao",
|
||||
flags = "saobem:",
|
||||
desc = "Paste the clipboard's contents",
|
||||
help =
|
||||
"Pastes the clipboard's contents.\n" +
|
||||
"Flags:\n" +
|
||||
" -a skips air blocks\n" +
|
||||
" -b pastes biomes if available\n" +
|
||||
" -e skips entities (default is don't skip!)\n" +
|
||||
" -m [<mask>] skips matching blocks in the clipboard\n" +
|
||||
" -o pastes at the original position\n" +
|
||||
" -s selects the region after pasting",
|
||||
" -s selects the region after pasting\n",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@ -148,18 +156,24 @@ public class ClipboardCommands {
|
||||
@Logging(PLACEMENT)
|
||||
public void paste(Player player, LocalSession session, EditSession editSession,
|
||||
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
|
||||
@Switch('s') boolean selectPasted) throws WorldEditException {
|
||||
@Switch('s') boolean selectPasted, @Switch('e') boolean skipEntities,
|
||||
@Switch('b') boolean pasteBiomes, @Switch('m') Mask sourceMask) throws WorldEditException {
|
||||
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
Region region = clipboard.getRegion();
|
||||
|
||||
BlockVector3 to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
|
||||
Operation operation = holder
|
||||
PasteBuilder builder = holder
|
||||
.createPaste(editSession)
|
||||
.to(to)
|
||||
.ignoreAirBlocks(ignoreAirBlocks)
|
||||
.build();
|
||||
.copyBiomes(pasteBiomes)
|
||||
.copyEntities(!skipEntities);
|
||||
if (sourceMask != null) {
|
||||
builder.maskSource(sourceMask);
|
||||
}
|
||||
Operation operation = builder.build();
|
||||
Operations.completeLegacy(operation);
|
||||
|
||||
if (selectPasted) {
|
||||
|
@ -115,6 +115,9 @@ class FlattenedClipboardTransform {
|
||||
BlockTransformExtent extent = new BlockTransformExtent(original, transform);
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(extent, original.getRegion(), original.getOrigin(), target, original.getOrigin());
|
||||
copy.setTransform(transform);
|
||||
if (original.hasBiomes()) {
|
||||
copy.setCopyingBiomes(true);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
@ -161,6 +161,11 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBiomes() {
|
||||
return biomes != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
if (biomes != null
|
||||
|
@ -20,6 +20,7 @@
|
||||
package com.sk89q.worldedit.extent.clipboard;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
@ -58,4 +59,15 @@ public interface Clipboard extends Extent {
|
||||
*/
|
||||
void setOrigin(BlockVector3 origin);
|
||||
|
||||
/**
|
||||
* Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector2)}
|
||||
* strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes.OCEAN} instead of {@code null}
|
||||
* if biomes aren't present. However, it might not be desired to set areas to ocean if the clipboard is defaulting
|
||||
* to ocean, instead of having biomes explicitly set.
|
||||
*
|
||||
* @return true if the clipboard has biome data set
|
||||
*/
|
||||
default boolean hasBiomes() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.function.biome;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Copies the biome from one extent to another.
|
||||
*/
|
||||
public class ExtentBiomeCopy implements FlatRegionFunction {
|
||||
|
||||
private final Extent source;
|
||||
private final Extent destination;
|
||||
private final BlockVector2 from;
|
||||
private final BlockVector2 to;
|
||||
private final Transform transform;
|
||||
|
||||
/**
|
||||
* Make a new biome copy.
|
||||
*
|
||||
* @param source the source extent
|
||||
* @param from the source offset
|
||||
* @param destination the destination extent
|
||||
* @param to the destination offset
|
||||
* @param transform a transform to apply to positions (after source offset, before destination offset)
|
||||
*/
|
||||
public ExtentBiomeCopy(Extent source, BlockVector2 from, Extent destination, BlockVector2 to, Transform transform) {
|
||||
checkNotNull(source);
|
||||
checkNotNull(from);
|
||||
checkNotNull(destination);
|
||||
checkNotNull(to);
|
||||
checkNotNull(transform);
|
||||
this.source = source;
|
||||
this.from = from;
|
||||
this.destination = destination;
|
||||
this.to = to;
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(BlockVector2 position) throws WorldEditException {
|
||||
BiomeType biome = source.getBiome(position);
|
||||
BlockVector2 orig = position.subtract(from);
|
||||
BlockVector2 transformed = transform.apply(orig.toVector3(0)).toVector2().toBlockPoint();
|
||||
|
||||
return destination.setBiome(transformed.add(to), biome);
|
||||
}
|
||||
}
|
@ -28,17 +28,24 @@ import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.CombinedRegionFunction;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
import com.sk89q.worldedit.function.FlatRegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.RegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.biome.ExtentBiomeCopy;
|
||||
import com.sk89q.worldedit.function.block.ExtentBlockCopy;
|
||||
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.transform.Identity;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.FlatRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
import java.util.List;
|
||||
@ -61,6 +68,7 @@ public class ForwardExtentCopy implements Operation {
|
||||
private Mask sourceMask = Masks.alwaysTrue();
|
||||
private boolean removingEntities;
|
||||
private boolean copyingEntities = true; // default to true for backwards compatibility, sort of
|
||||
private boolean copyingBiomes;
|
||||
private RegionFunction sourceFunction = null;
|
||||
private Transform transform = new Identity();
|
||||
private Transform currentTransform = null;
|
||||
@ -222,6 +230,27 @@ public class ForwardExtentCopy implements Operation {
|
||||
this.removingEntities = removingEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether biomes should be copied along with blocks.
|
||||
*
|
||||
* @return true if copying biomes
|
||||
*/
|
||||
public boolean isCopyingBiomes() {
|
||||
return copyingBiomes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether biomes should be copies along with blocks.
|
||||
*
|
||||
* @param copyingBiomes true if copying
|
||||
*/
|
||||
public void setCopyingBiomes(boolean copyingBiomes) {
|
||||
if (copyingBiomes && !(region instanceof FlatRegion)) {
|
||||
throw new UnsupportedOperationException("Can't copy biomes from region that doesn't implement FlatRegion");
|
||||
}
|
||||
this.copyingBiomes = copyingBiomes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of affected objects.
|
||||
*
|
||||
@ -254,6 +283,25 @@ public class ForwardExtentCopy implements Operation {
|
||||
|
||||
lastVisitor = blockVisitor;
|
||||
|
||||
if (!copyingBiomes && !copyingEntities) {
|
||||
return new DelegateOperation(this, blockVisitor);
|
||||
}
|
||||
|
||||
List<Operation> ops = Lists.newArrayList(blockVisitor);
|
||||
|
||||
if (copyingBiomes && region instanceof FlatRegion) { // double-check here even though we checked before
|
||||
ExtentBiomeCopy biomeCopy = new ExtentBiomeCopy(source, from.toBlockVector2(),
|
||||
destination, to.toBlockVector2(), currentTransform);
|
||||
Mask2D biomeMask = sourceMask.toMask2D();
|
||||
if (biomeMask != null) {
|
||||
FlatRegionMaskingFilter filteredBiomeCopy = new FlatRegionMaskingFilter(biomeMask, biomeCopy);
|
||||
FlatRegionVisitor biomeVisitor = new FlatRegionVisitor(((FlatRegion) region), filteredBiomeCopy);
|
||||
ops.add(biomeVisitor);
|
||||
} else {
|
||||
ops.add(new FlatRegionVisitor(((FlatRegion) region), biomeCopy));
|
||||
}
|
||||
}
|
||||
|
||||
if (copyingEntities) {
|
||||
ExtentEntityCopy entityCopy = new ExtentEntityCopy(from.toVector3(), destination, to.toVector3(), currentTransform);
|
||||
entityCopy.setRemoving(removingEntities);
|
||||
@ -263,10 +311,10 @@ public class ForwardExtentCopy implements Operation {
|
||||
return properties != null && !properties.isPasteable();
|
||||
});
|
||||
EntityVisitor entityVisitor = new EntityVisitor(entities.iterator(), entityCopy);
|
||||
return new DelegateOperation(this, new OperationQueue(blockVisitor, entityVisitor));
|
||||
} else {
|
||||
return new DelegateOperation(this, blockVisitor);
|
||||
ops.add(entityVisitor);
|
||||
}
|
||||
|
||||
return new DelegateOperation(this, new OperationQueue(ops));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
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.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -39,8 +42,12 @@ public class PasteBuilder {
|
||||
private final Transform transform;
|
||||
private final Extent targetExtent;
|
||||
|
||||
private Mask sourceMask = Masks.alwaysTrue();
|
||||
|
||||
private BlockVector3 to = BlockVector3.ZERO;
|
||||
private boolean ignoreAirBlocks;
|
||||
private boolean copyEntities = true; // default because it used to be this way
|
||||
private boolean copyBiomes;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
@ -67,6 +74,19 @@ public class PasteBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom mask of blocks to ignore from the source.
|
||||
* This provides a more flexible alternative to {@link #ignoreAirBlocks(boolean)}, for example
|
||||
* one might want to ignore structure void if copying a Minecraft Structure, etc.
|
||||
*
|
||||
* @param sourceMask
|
||||
* @return this builder instance
|
||||
*/
|
||||
public PasteBuilder maskSource(Mask sourceMask) {
|
||||
this.sourceMask = sourceMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether air blocks in the source are skipped over when pasting.
|
||||
*
|
||||
@ -77,6 +97,29 @@ public class PasteBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the copy should include source entities.
|
||||
* Note that this is true by default for legacy reasons.
|
||||
*
|
||||
* @param copyEntities
|
||||
* @return this builder instance
|
||||
*/
|
||||
public PasteBuilder copyEntities(boolean copyEntities) {
|
||||
this.copyEntities = copyEntities;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the copy should include source biomes (if available).
|
||||
*
|
||||
* @param copyBiomes
|
||||
* @return this builder instance
|
||||
*/
|
||||
public PasteBuilder copyBiomes(boolean copyBiomes) {
|
||||
this.copyBiomes = copyBiomes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the operation.
|
||||
*
|
||||
@ -87,8 +130,13 @@ public class PasteBuilder {
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), targetExtent, to);
|
||||
copy.setTransform(transform);
|
||||
if (ignoreAirBlocks) {
|
||||
copy.setSourceMask(new ExistingBlockMask(clipboard));
|
||||
copy.setSourceMask(sourceMask == Masks.alwaysTrue() ? new ExistingBlockMask(clipboard)
|
||||
: new MaskIntersection(sourceMask, new ExistingBlockMask(clipboard)));
|
||||
} else {
|
||||
copy.setSourceMask(sourceMask);
|
||||
}
|
||||
copy.setCopyingEntities(copyEntities);
|
||||
copy.setCopyingBiomes(copyBiomes && clipboard.hasBiomes());
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren