From 780ccd37ec0198e7ef88a4d6933658b9f2fc3508 Mon Sep 17 00:00:00 2001 From: sk89q Date: Tue, 16 Nov 2010 20:03:54 -0800 Subject: [PATCH] Added recursive fill. --- src/EditSession.java | 110 ++++++++++++++++++++++++------------- src/WorldEditListener.java | 15 +++-- 2 files changed, 81 insertions(+), 44 deletions(-) diff --git a/src/EditSession.java b/src/EditSession.java index f99280fb7..acdacd027 100644 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -329,16 +329,15 @@ public class EditSession { /** * Fills an area recursively in the X/Z directions. * - * @param x - * @param z * @param origin * @param block * @param radius * @param depth + * @param recursive * @return number of blocks affected */ - public int fillXZ(int x, int z, Vector origin, BaseBlock block, - int radius, int depth) + public int fillXZ(Vector origin, BaseBlock block, + int radius, int depth, boolean recursive) throws MaxChangedBlocksException { int affected = 0; @@ -349,37 +348,55 @@ public class EditSession { HashSet visited = new HashSet(); Stack queue = new Stack(); - queue.push(new BlockVector(x, 0, z)); + 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 (visited.contains(pt)) { + if (cy < 0 || cy > originY || 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 (recursive) { + if (origin.distance(pt) > radius) { + continue; + } - if (dist > radius) { - continue; - } + if (getBlock(pt).isAir()) { + if (setBlock(pt, block)) { + affected++; + } + } else { + continue; + } - if (getBlock(new Vector(cx, originY, cz)).isAir()) { - affected += fillY(cx, originY, cz, block, minY); + queue.push(new BlockVector(cx, cy - 1, cz)); + queue.push(new BlockVector(cx, cy + 1, cz)); } 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, 0, cz)); - queue.push(new BlockVector(cx, 0, cz + 1)); - queue.push(new BlockVector(cx, 0, cz - 1)); + 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; @@ -417,16 +434,15 @@ public class EditSession { /** * Fills an area recursively in the X/Z directions. * - * @param x - * @param z * @param origin * @param pattern * @param radius * @param depth + * @param recursive * @return number of blocks affected */ - public int fillXZ(int x, int z, Vector origin, Pattern pattern, - int radius, int depth) + public int fillXZ(Vector origin, Pattern pattern, + int radius, int depth, boolean recursive) throws MaxChangedBlocksException { int affected = 0; @@ -437,37 +453,55 @@ public class EditSession { HashSet visited = new HashSet(); Stack queue = new Stack(); - queue.push(new BlockVector(x, 0, z)); + 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 (visited.contains(pt)) { + if (cy < 0 || cy > originY || 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 (recursive) { + if (origin.distance(pt) > radius) { + continue; + } - if (dist > radius) { - continue; - } + if (getBlock(pt).isAir()) { + if (setBlock(pt, pattern.next(pt))) { + affected++; + } + } else { + continue; + } - if (getBlock(new Vector(cx, originY, cz)).isAir()) { - affected += fillY(cx, originY, cz, pattern, minY); + queue.push(new BlockVector(cx, cy - 1, cz)); + queue.push(new BlockVector(cx, cy + 1, cz)); } 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, 0, cz)); - queue.push(new BlockVector(cx, 0, cz + 1)); - queue.push(new BlockVector(cx, 0, cz - 1)); + 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; diff --git a/src/WorldEditListener.java b/src/WorldEditListener.java index b1cdc6e7d..0c62e68a2 100644 --- a/src/WorldEditListener.java +++ b/src/WorldEditListener.java @@ -130,6 +130,7 @@ public class WorldEditListener extends PluginListener { commands.put("//load", "[Filename] - Load .schematic into clipboard"); commands.put("//save", "[Filename] - Save clipboard to .schematic"); commands.put("//fill", "[ID] [Radius] - Fill a hole"); + commands.put("//fillr", "[ID] [Radius] - Fill a hole fully recursively"); commands.put("//drain", "[Radius] - Drain nearby water/lava pools"); commands.put("//limit", "[Num] - See documentation"); commands.put("//mode", "[Mode] - Set super pickaxe mode (single/recursive/area)"); @@ -724,8 +725,10 @@ public class WorldEditListener extends PluginListener { return true; // Fill a hole - } else if (split[0].equalsIgnoreCase("//fill")) { - checkArgs(split, 2, 3, split[0]); + } else if (split[0].equalsIgnoreCase("//fill") + || split[0].equalsIgnoreCase("//fillr")) { + boolean recursive = split[0].equalsIgnoreCase("//fillr"); + checkArgs(split, 2, recursive ? 2 : 3, split[0]); Pattern pattern = getBlockPattern(split[1]); int radius = Math.max(1, Integer.parseInt(split[2])); checkMaxRadius(radius); @@ -734,11 +737,11 @@ public class WorldEditListener extends PluginListener { Vector pos = session.getPlacementPosition(player); int affected = 0; if (pattern instanceof SingleBlockPattern) { - affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(), - pos, ((SingleBlockPattern)pattern).getBlock(), radius, depth); + affected = editSession.fillXZ(pos, + ((SingleBlockPattern)pattern).getBlock(), + radius, depth, recursive); } else { - affected = editSession.fillXZ((int)pos.getX(), (int)pos.getZ(), - pos, pattern, radius, depth); + affected = editSession.fillXZ(pos, pattern, radius, depth, recursive); } player.print(affected + " block(s) have been created.");