Added ForwardExtentCopy and ExtentBlockCopy.

This commit is contained in:
sk89q 2014-03-30 03:08:06 -07:00
parent 9aa3ae15d0
commit e3a42db309
2 changed files with 247 additions and 0 deletions

View File

@ -0,0 +1,70 @@
/*
* 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 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.function.block;
import com.sk89q.worldedit.Extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.math.transform.Transform;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Copies blocks from one extent to another.
*/
public class ExtentBlockCopy implements RegionFunction {
private final Extent source;
private final Extent destination;
private final Vector from;
private final Vector to;
private final Transform transform;
/**
* Make a new 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 ExtentBlockCopy(Extent source, Vector from, Extent destination, Vector 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(Vector position) throws WorldEditException {
BaseBlock block = source.getBlock(position);
return destination.setBlock(transform.apply(position.subtract(from)).add(to), block, true);
}
}

View File

@ -0,0 +1,177 @@
/*
* 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 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.function.operation;
import com.sk89q.worldedit.Extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionMaskingFilter;
import com.sk89q.worldedit.function.block.ExtentBlockCopy;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Makes a copy of a portion of one extent to another extent or another point.
* </p>
* This is a forward extent copy, meaning that it iterates over the blocks in the
* source extent, and will copy as many blocks as there are in the source.
* Therefore, interpolation will not occur to fill in the gaps.
*/
public class ForwardExtentCopy implements Operation {
private final Extent source;
private final Extent destination;
private final Region region;
private final Vector to;
private int repetitions = 1;
private Mask sourceMask = Masks.alwaysTrue();
private Transform transform = new Identity();
private Transform currentTransform = null;
private RegionVisitor lastVisitor;
private int affected;
/**
* Create a new copy.
*
* @param source the source extent
* @param region the region to copy
* @param destination the destination extent
* @param to the destination position, starting from the the lowest X, Y, Z
*/
public ForwardExtentCopy(Extent source, Region region, Extent destination, Vector to) {
checkNotNull(source);
checkNotNull(region);
checkNotNull(destination);
checkNotNull(to);
this.source = source;
this.destination = destination;
this.region = region;
this.to = to;
}
/**
* Get the transformation that will occur on every point.
* </p>
* The transformation will stack with each repetition.
*
* @return a transformation
*/
public Transform getTransform() {
return transform;
}
/**
* Set the transformation that will occur on every point.
*
* @param transform a transformation
* @see #getTransform()
*/
public void setTransform(Transform transform) {
checkNotNull(transform);
this.transform = transform;
}
/**
* Get the mask that gets applied to the source extent.
* </p>
* This mask can be used to filter what will be copied from the source.
*
* @return a source mask
*/
public Mask getSourceMask() {
return sourceMask;
}
/**
* Set a mask that gets applied to the source extent.
*
* @param sourceMask a source mask
* @see #getSourceMask()
*/
public void setSourceMask(Mask sourceMask) {
checkNotNull(sourceMask);
this.sourceMask = sourceMask;
}
/**
* Get the number of repetitions left.
*
* @return the number of repetitions
*/
public int getRepetitions() {
return repetitions;
}
/**
* Set the number of repetitions left.
*
* @param repetitions the number of repetitions
*/
public void setRepetitions(int repetitions) {
checkArgument(repetitions >= 0, "number of repetitions must be non-negative");
this.repetitions = repetitions;
}
/**
* Get the number of affected objects.
*
* @return the number of affected
*/
public int getAffected() {
return affected;
}
@Override
public Operation resume() throws WorldEditException {
if (lastVisitor != null) {
affected += lastVisitor.getAffected();
lastVisitor = null;
}
if (repetitions > 0) {
repetitions--;
if (currentTransform == null) {
currentTransform = transform;
}
ExtentBlockCopy copy = new ExtentBlockCopy(source, region.getMinimumPoint(), destination, to, currentTransform);
RegionMaskingFilter filter = new RegionMaskingFilter(sourceMask, copy);
RegionVisitor visitor = new RegionVisitor(region, filter);
lastVisitor = visitor;
currentTransform = currentTransform.combine(transform);
return new DelegateOperation(this, visitor);
} else {
return null;
}
}
@Override
public void cancel() {
}
}