Added recursive fill.

This commit is contained in:
sk89q 2010-11-16 20:03:54 -08:00
parent 06d87a84cc
commit 780ccd37ec
2 changed files with 81 additions and 44 deletions

View File

@ -329,16 +329,15 @@ public class EditSession {
/** /**
* Fills an area recursively in the X/Z directions. * Fills an area recursively in the X/Z directions.
* *
* @param x
* @param z
* @param origin * @param origin
* @param block * @param block
* @param radius * @param radius
* @param depth * @param depth
* @param recursive
* @return number of blocks affected * @return number of blocks affected
*/ */
public int fillXZ(int x, int z, Vector origin, BaseBlock block, public int fillXZ(Vector origin, BaseBlock block,
int radius, int depth) int radius, int depth, boolean recursive)
throws MaxChangedBlocksException { throws MaxChangedBlocksException {
int affected = 0; int affected = 0;
@ -349,37 +348,55 @@ public class EditSession {
HashSet<BlockVector> visited = new HashSet<BlockVector>(); HashSet<BlockVector> visited = new HashSet<BlockVector>();
Stack<BlockVector> queue = new Stack<BlockVector>(); Stack<BlockVector> queue = new Stack<BlockVector>();
queue.push(new BlockVector(x, 0, z)); queue.push(new BlockVector(originX, originY, originZ));
while (!queue.empty()) { while (!queue.empty()) {
BlockVector pt = queue.pop(); BlockVector pt = queue.pop();
int cx = pt.getBlockX(); int cx = pt.getBlockX();
int cy = pt.getBlockY();
int cz = pt.getBlockZ(); int cz = pt.getBlockZ();
if (visited.contains(pt)) { if (cy < 0 || cy > originY || visited.contains(pt)) {
continue; continue;
} }
visited.add(pt); visited.add(pt);
double dist = Math.sqrt(Math.pow(originX - cx, 2) if (recursive) {
+ Math.pow(originZ - cz, 2)); if (origin.distance(pt) > radius) {
int minY = originY - depth + 1; continue;
}
if (dist > radius) { if (getBlock(pt).isAir()) {
continue; if (setBlock(pt, block)) {
} affected++;
}
} else {
continue;
}
if (getBlock(new Vector(cx, originY, cz)).isAir()) { queue.push(new BlockVector(cx, cy - 1, cz));
affected += fillY(cx, originY, cz, block, minY); queue.push(new BlockVector(cx, cy + 1, cz));
} else { } else {
continue; 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, 0, cz)); queue.push(new BlockVector(cx + 1, cy, cz));
queue.push(new BlockVector(cx - 1, 0, cz)); queue.push(new BlockVector(cx - 1, cy, cz));
queue.push(new BlockVector(cx, 0, cz + 1)); queue.push(new BlockVector(cx, cy, cz + 1));
queue.push(new BlockVector(cx, 0, cz - 1)); queue.push(new BlockVector(cx, cy, cz - 1));
} }
return affected; return affected;
@ -417,16 +434,15 @@ public class EditSession {
/** /**
* Fills an area recursively in the X/Z directions. * Fills an area recursively in the X/Z directions.
* *
* @param x
* @param z
* @param origin * @param origin
* @param pattern * @param pattern
* @param radius * @param radius
* @param depth * @param depth
* @param recursive
* @return number of blocks affected * @return number of blocks affected
*/ */
public int fillXZ(int x, int z, Vector origin, Pattern pattern, public int fillXZ(Vector origin, Pattern pattern,
int radius, int depth) int radius, int depth, boolean recursive)
throws MaxChangedBlocksException { throws MaxChangedBlocksException {
int affected = 0; int affected = 0;
@ -437,37 +453,55 @@ public class EditSession {
HashSet<BlockVector> visited = new HashSet<BlockVector>(); HashSet<BlockVector> visited = new HashSet<BlockVector>();
Stack<BlockVector> queue = new Stack<BlockVector>(); Stack<BlockVector> queue = new Stack<BlockVector>();
queue.push(new BlockVector(x, 0, z)); queue.push(new BlockVector(originX, originY, originZ));
while (!queue.empty()) { while (!queue.empty()) {
BlockVector pt = queue.pop(); BlockVector pt = queue.pop();
int cx = pt.getBlockX(); int cx = pt.getBlockX();
int cy = pt.getBlockY();
int cz = pt.getBlockZ(); int cz = pt.getBlockZ();
if (visited.contains(pt)) { if (cy < 0 || cy > originY || visited.contains(pt)) {
continue; continue;
} }
visited.add(pt); visited.add(pt);
double dist = Math.sqrt(Math.pow(originX - cx, 2) if (recursive) {
+ Math.pow(originZ - cz, 2)); if (origin.distance(pt) > radius) {
int minY = originY - depth + 1; continue;
}
if (dist > radius) { if (getBlock(pt).isAir()) {
continue; if (setBlock(pt, pattern.next(pt))) {
} affected++;
}
} else {
continue;
}
if (getBlock(new Vector(cx, originY, cz)).isAir()) { queue.push(new BlockVector(cx, cy - 1, cz));
affected += fillY(cx, originY, cz, pattern, minY); queue.push(new BlockVector(cx, cy + 1, cz));
} else { } else {
continue; 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, 0, cz)); queue.push(new BlockVector(cx + 1, cy, cz));
queue.push(new BlockVector(cx - 1, 0, cz)); queue.push(new BlockVector(cx - 1, cy, cz));
queue.push(new BlockVector(cx, 0, cz + 1)); queue.push(new BlockVector(cx, cy, cz + 1));
queue.push(new BlockVector(cx, 0, cz - 1)); queue.push(new BlockVector(cx, cy, cz - 1));
} }
return affected; return affected;

View File

@ -130,6 +130,7 @@ public class WorldEditListener extends PluginListener {
commands.put("//load", "[Filename] - Load .schematic into clipboard"); commands.put("//load", "[Filename] - Load .schematic into clipboard");
commands.put("//save", "[Filename] - Save clipboard to .schematic"); commands.put("//save", "[Filename] - Save clipboard to .schematic");
commands.put("//fill", "[ID] [Radius] <Depth> - Fill a hole"); commands.put("//fill", "[ID] [Radius] <Depth> - Fill a hole");
commands.put("//fillr", "[ID] [Radius] - Fill a hole fully recursively");
commands.put("//drain", "[Radius] - Drain nearby water/lava pools"); commands.put("//drain", "[Radius] - Drain nearby water/lava pools");
commands.put("//limit", "[Num] - See documentation"); commands.put("//limit", "[Num] - See documentation");
commands.put("//mode", "[Mode] <Size> - Set super pickaxe mode (single/recursive/area)"); commands.put("//mode", "[Mode] <Size> - Set super pickaxe mode (single/recursive/area)");
@ -724,8 +725,10 @@ public class WorldEditListener extends PluginListener {
return true; return true;
// Fill a hole // Fill a hole
} else if (split[0].equalsIgnoreCase("//fill")) { } else if (split[0].equalsIgnoreCase("//fill")
checkArgs(split, 2, 3, split[0]); || split[0].equalsIgnoreCase("//fillr")) {
boolean recursive = split[0].equalsIgnoreCase("//fillr");
checkArgs(split, 2, recursive ? 2 : 3, split[0]);
Pattern pattern = getBlockPattern(split[1]); Pattern pattern = getBlockPattern(split[1]);
int radius = Math.max(1, Integer.parseInt(split[2])); int radius = Math.max(1, Integer.parseInt(split[2]));
checkMaxRadius(radius); checkMaxRadius(radius);
@ -734,11 +737,11 @@ public class WorldEditListener extends PluginListener {
Vector pos = session.getPlacementPosition(player); Vector pos = session.getPlacementPosition(player);
int affected = 0; int affected = 0;
if (pattern instanceof SingleBlockPattern) { if (pattern instanceof SingleBlockPattern) {
affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(), affected = editSession.fillXZ(pos,
pos, ((SingleBlockPattern)pattern).getBlock(), radius, depth); ((SingleBlockPattern)pattern).getBlock(),
radius, depth, recursive);
} else { } else {
affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(), affected = editSession.fillXZ(pos, pattern, radius, depth, recursive);
pos, pattern, radius, depth);
} }
player.print(affected + " block(s) have been created."); player.print(affected + " block(s) have been created.");