Added pattern support to //replace and //fill.

This commit is contained in:
sk89q 2010-11-16 14:07:52 -08:00
parent ff7df41823
commit 06d87a84cc
2 changed files with 174 additions and 14 deletions

View File

@ -414,6 +414,94 @@ public class EditSession {
return affected;
}
/**
* Fills an area recursively in the X/Z directions.
*
* @param x
* @param z
* @param origin
* @param pattern
* @param radius
* @param depth
* @return number of blocks affected
*/
public int fillXZ(int x, int z, Vector origin, Pattern pattern,
int radius, int depth)
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(x, 0, z));
while (!queue.empty()) {
BlockVector pt = queue.pop();
int cx = pt.getBlockX();
int cz = pt.getBlockZ();
if (visited.contains(pt)) {
continue;
}
visited.add(pt);
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(new Vector(cx, originY, cz)).isAir()) {
affected += fillY(cx, originY, cz, pattern, minY);
} else {
continue;
}
queue.push(new BlockVector(cx + 1, 0, cz));
queue.push(new BlockVector(cx - 1, 0, cz));
queue.push(new BlockVector(cx, 0, cz + 1));
queue.push(new BlockVector(cx, 0, 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)
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, pattern.next(pt));
affected++;
} else {
break;
}
}
return affected;
}
/**
* Remove blocks above.
*
@ -661,6 +749,64 @@ public class EditSession {
return affected;
}
/**
* Replaces all the blocks of a type inside a region to another block type.
*
* @param region
* @param fromBlockType -1 for non-air
* @param pattern
* @return number of blocks affected
* @throws MaxChangedBlocksException
*/
public int replaceBlocks(Region region, Set<Integer> fromBlockTypes,
Pattern pattern)
throws MaxChangedBlocksException {
int affected = 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);
int curBlockType = getBlock(pt).getID();
if ((fromBlockTypes == null && curBlockType != 0) ||
(fromBlockTypes != null &&
fromBlockTypes.contains(curBlockType))) {
if (setBlock(pt, pattern.next(pt))) {
affected++;
}
}
}
}
}
} else {
for (Vector pt : region) {
int curBlockType = getBlock(pt).getID();
if (fromBlockTypes == null && curBlockType != 0 ||
fromBlockTypes.contains(curBlockType)) {
if (setBlock(pt, pattern.next(pt))) {
affected++;
}
}
}
}
return affected;
}
/**
* Make faces of the region (as if it was a cuboid if it's not).
*

View File

@ -308,14 +308,15 @@ public class WorldEditListener extends PluginListener {
* Get a list of blocks as a set.
*
* @param list
* @params allBlocksAllowed
* @return set
*/
public Set<Integer> getBlockIDs(String list) throws UnknownItemException,
DisallowedItemException {
public Set<Integer> getBlockIDs(String list, boolean allBlocksAllowed)
throws UnknownItemException, DisallowedItemException {
String[] items = list.split(",");
Set<Integer> blocks = new HashSet<Integer>();
for (String s : items) {
blocks.add(getBlock(s).getID());
blocks.add(getBlock(s, allBlocksAllowed).getID());
}
return blocks;
}
@ -725,14 +726,20 @@ public class WorldEditListener extends PluginListener {
// Fill a hole
} else if (split[0].equalsIgnoreCase("//fill")) {
checkArgs(split, 2, 3, split[0]);
BaseBlock block = getBlock(split[1]);
Pattern pattern = getBlockPattern(split[1]);
int radius = Math.max(1, Integer.parseInt(split[2]));
checkMaxRadius(radius);
int depth = split.length > 3 ? Math.max(1, Integer.parseInt(split[3])) : 1;
Vector pos = session.getPlacementPosition(player);
int affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(),
pos, block, radius, depth);
int affected = 0;
if (pattern instanceof SingleBlockPattern) {
affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(),
pos, ((SingleBlockPattern)pattern).getBlock(), radius, depth);
} else {
affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(),
pos, pattern, radius, depth);
}
player.print(affected + " block(s) have been created.");
return true;
@ -936,17 +943,24 @@ public class WorldEditListener extends PluginListener {
// Replace all blocks in the region
} else if(split[0].equalsIgnoreCase("//replace")) {
checkArgs(split, 1, 2, split[0]);
Set<Integer> from;
BaseBlock to;
Pattern to;
if (split.length == 2) {
from = null;
to = getBlock(split[1], true);
to = getBlockPattern(split[1]);
} else {
from = getBlockIDs(split[1]);
to = getBlock(split[2]);
from = getBlockIDs(split[1], true);
to = getBlockPattern(split[2]);
}
int affected = 0;
if (to instanceof SingleBlockPattern) {
affected = editSession.replaceBlocks(session.getRegion(), from,
((SingleBlockPattern)to).getBlock());
} else {
affected = editSession.replaceBlocks(session.getRegion(), from, to);
}
int affected = editSession.replaceBlocks(session.getRegion(), from, to);
player.print(affected + " block(s) have been replaced.");
return true;
@ -959,9 +973,9 @@ public class WorldEditListener extends PluginListener {
BaseBlock to;
if (split.length == 3) {
from = null;
to = getBlock(split[2], true);
to = getBlock(split[2]);
} else {
from = getBlockIDs(split[2]);
from = getBlockIDs(split[2], true);
to = getBlock(split[3]);
}