Changed //count, //fill, //fillr to use visitors.

This commit is contained in:
sk89q 2014-03-26 23:10:47 -07:00 committed by TomyLobo
parent 2562a2f577
commit dbb7b085f0
2 changed files with 47 additions and 233 deletions

View File

@ -29,15 +29,15 @@ import com.sk89q.worldedit.expression.ExpressionException;
import com.sk89q.worldedit.expression.runtime.RValue;
import com.sk89q.worldedit.generator.ForestGenerator;
import com.sk89q.worldedit.generator.GardenPatchGenerator;
import com.sk89q.worldedit.operation.FlatRegionVisitor;
import com.sk89q.worldedit.operation.GroundScatterFunction;
import com.sk89q.worldedit.interpolation.Interpolation;
import com.sk89q.worldedit.interpolation.KochanekBartelsInterpolation;
import com.sk89q.worldedit.interpolation.Node;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.operation.OperationHelper;
import com.sk89q.worldedit.masks.*;
import com.sk89q.worldedit.operation.*;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.EllipsoidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.shape.ArbitraryBiomeShape;
@ -538,47 +538,16 @@ public class EditSession {
/**
* Count the number of blocks of a list of types in a region.
*
* @param region
* @param searchBlocks
* @return
* @param region the region
* @param searchBlocks the list of blocks to search
* @return the number of blocks that matched the pattern
*/
public int countBlocks(Region region, Set<BaseBlock> searchBlocks) {
int count = 0;
if (region instanceof CuboidRegion) {
// Doing this for speed
Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint();
int minX = min.getBlockX();
int minY = min.getBlockY();
int minZ = min.getBlockZ();
int maxX = max.getBlockX();
int maxY = max.getBlockY();
int maxZ = max.getBlockZ();
for (int x = minX; x <= maxX; ++x) {
for (int y = minY; y <= maxY; ++y) {
for (int z = minZ; z <= maxZ; ++z) {
Vector pt = new Vector(x, y, z);
BaseBlock compare = new BaseBlock(getBlockType(pt), getBlockData(pt));
if (BaseBlock.containsFuzzy(searchBlocks, compare)) {
++count;
}
}
}
}
} else {
for (Vector pt : region) {
BaseBlock compare = new BaseBlock(getBlockType(pt), getBlockData(pt));
if (BaseBlock.containsFuzzy(searchBlocks, compare)) {
++count;
}
}
}
return count;
FuzzyBlockMask mask = new FuzzyBlockMask(searchBlocks);
BlockCount counter = new BlockCount(this, mask);
RegionVisitor visitor = new RegionVisitor(region, counter);
OperationHelper.completeBlindly(visitor); // We can't throw exceptions, nor do we expect any
return counter.getCount();
}
/**
@ -803,211 +772,56 @@ public class EditSession {
/**
* Fills an area recursively in the X/Z directions.
*
* @param origin
* @param block
* @param radius
* @param depth
* @param recursive
* @param origin the location to start from
* @param block the block to fill with
* @param radius the radius of the spherical area to fill
* @param depth the maximum depth, starting from the origin
* @param recursive whether a breadth-first search should be performed
* @return number of blocks affected
* @throws MaxChangedBlocksException
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int fillXZ(Vector origin, BaseBlock block, double radius, int depth,
boolean recursive) throws MaxChangedBlocksException {
int affected = 0;
int originX = origin.getBlockX();
int originY = origin.getBlockY();
int originZ = origin.getBlockZ();
HashSet<BlockVector> visited = new HashSet<BlockVector>();
Stack<BlockVector> queue = new Stack<BlockVector>();
queue.push(new BlockVector(originX, originY, originZ));
while (!queue.empty()) {
BlockVector pt = queue.pop();
int cx = pt.getBlockX();
int cy = pt.getBlockY();
int cz = pt.getBlockZ();
if (cy < 0 || cy > originY || visited.contains(pt)) {
continue;
}
visited.add(pt);
if (recursive) {
if (origin.distance(pt) > radius) {
continue;
}
if (getBlock(pt).isAir()) {
if (setBlock(pt, block)) {
++affected;
}
} else {
continue;
}
queue.push(new BlockVector(cx, cy - 1, cz));
queue.push(new BlockVector(cx, cy + 1, cz));
} else {
double dist = Math.sqrt(Math.pow(originX - cx, 2)
+ Math.pow(originZ - cz, 2));
int minY = originY - depth + 1;
if (dist > radius) {
continue;
}
if (getBlock(pt).isAir()) {
affected += fillY(cx, originY, cz, block, minY);
} else {
continue;
}
}
queue.push(new BlockVector(cx + 1, cy, cz));
queue.push(new BlockVector(cx - 1, cy, cz));
queue.push(new BlockVector(cx, cy, cz + 1));
queue.push(new BlockVector(cx, cy, cz - 1));
}
return affected;
}
/**
* Recursively fills a block and below until it hits another block.
*
* @param x
* @param cy
* @param z
* @param block
* @param minY
* @throws MaxChangedBlocksException
* @return
*/
private int fillY(int x, int cy, int z, BaseBlock block, int minY)
public int fillXZ(Vector origin, BaseBlock block, double radius, int depth, boolean recursive)
throws MaxChangedBlocksException {
int affected = 0;
for (int y = cy; y >= minY; --y) {
Vector pt = new Vector(x, y, z);
if (getBlock(pt).isAir()) {
setBlock(pt, block);
++affected;
} else {
break;
}
}
return affected;
return fillXZ(origin, new SingleBlockPattern(block), radius, depth, recursive);
}
/**
* Fills an area recursively in the X/Z directions.
*
* @param origin
* @param pattern
* @param radius
* @param depth
* @param recursive
* @param pattern the pattern to fill with
* @param radius the radius of the spherical area to fill
* @param depth the maximum depth, starting from the origin
* @param recursive whether a breadth-first search should be performed
* @return number of blocks affected
* @throws MaxChangedBlocksException
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int fillXZ(Vector origin, Pattern pattern, double radius, int depth,
boolean recursive) throws MaxChangedBlocksException {
int affected = 0;
int originX = origin.getBlockX();
int originY = origin.getBlockY();
int originZ = origin.getBlockZ();
HashSet<BlockVector> visited = new HashSet<BlockVector>();
Stack<BlockVector> queue = new Stack<BlockVector>();
queue.push(new BlockVector(originX, originY, originZ));
while (!queue.empty()) {
BlockVector pt = queue.pop();
int cx = pt.getBlockX();
int cy = pt.getBlockY();
int cz = pt.getBlockZ();
if (cy < 0 || cy > originY || visited.contains(pt)) {
continue;
}
visited.add(pt);
if (recursive) {
if (origin.distance(pt) > radius) {
continue;
}
if (getBlock(pt).isAir()) {
if (setBlock(pt, pattern.next(pt))) {
++affected;
}
} else {
continue;
}
queue.push(new BlockVector(cx, cy - 1, cz));
queue.push(new BlockVector(cx, cy + 1, cz));
} else {
double dist = Math.sqrt(Math.pow(originX - cx, 2)
+ Math.pow(originZ - cz, 2));
int minY = originY - depth + 1;
if (dist > radius) {
continue;
}
if (getBlock(pt).isAir()) {
affected += fillY(cx, originY, cz, pattern, minY);
} else {
continue;
}
}
queue.push(new BlockVector(cx + 1, cy, cz));
queue.push(new BlockVector(cx - 1, cy, cz));
queue.push(new BlockVector(cx, cy, cz + 1));
queue.push(new BlockVector(cx, cy, cz - 1));
}
return affected;
}
/**
* Recursively fills a block and below until it hits another block.
*
* @param x
* @param cy
* @param z
* @param pattern
* @param minY
* @throws MaxChangedBlocksException
* @return
*/
private int fillY(int x, int cy, int z, Pattern pattern, int minY)
public int fillXZ(Vector origin, Pattern pattern, double radius, int depth, boolean recursive)
throws MaxChangedBlocksException {
int affected = 0;
for (int y = cy; y >= minY; --y) {
Vector pt = new Vector(x, y, z);
CombinedMask mask = new CombinedMask(
new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))),
new BoundedYMask(origin.getBlockY() - depth + 1, origin.getBlockY()),
new InvertedMask(new ExistingBlockMask()));
if (getBlock(pt).isAir()) {
setBlock(pt, pattern.next(pt));
++affected;
} else {
break;
}
// Want to replace blocks
BlockReplace replace = new BlockReplace(this, pattern);
// Pick how we're going to visit blocks
RecursiveVisitor visitor;
if (recursive) {
visitor = new RecursiveVisitor(this, mask, replace);
} else {
visitor = new DownwardVisitor(this, mask, replace, origin.getBlockY());
}
return affected;
// Start at the origin
visitor.visit(origin);
// Execute
OperationHelper.completeLegacy(visitor);
return visitor.getAffected();
}
/**

View File

@ -91,7 +91,7 @@ public class UtilityCommands {
Pattern pattern = we.getBlockPattern(player, args.getString(0));
double radius = Math.max(1, args.getDouble(1));
we.checkMaxRadius(radius);
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : 1;
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : Integer.MAX_VALUE;
Vector pos = session.getPlacementPosition(player);
int affected = 0;