From f64cc76906386d0fcfa9e4debffaf4b4d6db8557 Mon Sep 17 00:00:00 2001 From: sk89q Date: Mon, 11 Oct 2010 11:17:32 -0700 Subject: [PATCH] Added /editdrain, added BlockPoint that compares using ints. --- src/EditSession.java | 73 +++++++++++++++++++++++++ src/WorldEdit.java | 10 ++++ src/com/sk89q/worldedit/BlockPoint.java | 65 ++++++++++++++++++++++ src/com/sk89q/worldedit/Point.java | 37 ++++++++++++- 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 src/com/sk89q/worldedit/BlockPoint.java diff --git a/src/EditSession.java b/src/EditSession.java index 7e956bdd0..0b69515d9 100644 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -621,4 +621,77 @@ public class EditSession { return affected; } + + /** + * Drain nearby pools of water or lava. + * + * @param pos + * @param radius + * @return number of blocks affected + * @throws MaxChangedBlocksException + */ + public int drainArea(Point pos, int radius) throws MaxChangedBlocksException { + int affected = 0; + + HashSet visited = new HashSet(); + + for (int x = pos.getBlockX() - 1; x <= pos.getBlockX() + 1; x++) { + for (int z = pos.getBlockZ() - 1; z <= pos.getBlockZ() + 1; z++) { + for (int y = pos.getBlockY() - 1; y <= pos.getBlockY() + 1; y++) { + affected += drainPool(new Point(x, y, z), pos, radius, visited); + } + } + } + + return affected; + } + + /** + * Drains a water or lava block and any lava/water blocks next to it. + * + * @param pos + * @param origin + * @param radius + * @param visited + * @return number of blocks affected + * @throws MaxChangedBlocksException + */ + private int drainPool(Point pos, Point origin, int radius, HashSet visited) + throws MaxChangedBlocksException { + int type = getBlock(pos); + int affected = 0; + + if (type != 8 && type != 9 && type != 10 && type != 11) { + return 0; + } + + BlockPoint blockPos = new BlockPoint(pos); + + if (visited.contains(blockPos)) { + return 0; + } + visited.add(blockPos); + + if (pos.distance(origin) > radius) { + return 0; + } + + for (int x = pos.getBlockX() - 1; x <= pos.getBlockX() + 1; x++) { + for (int z = pos.getBlockZ() - 1; z <= pos.getBlockZ() + 1; z++) { + for (int y = pos.getBlockY() - 1; y <= pos.getBlockY() + 1; y++) { + Point newPos = new Point(x, y, z); + + if (!pos.equals(newPos)) { + affected += drainPool(newPos, origin, radius, visited); + } + } + } + } + + if (setBlock(pos, 0)) { + affected++; + } + + return affected; + } } diff --git a/src/WorldEdit.java b/src/WorldEdit.java index 8a9f9ef8d..88be0dc45 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -73,6 +73,7 @@ public class WorldEdit extends Plugin { commands.put("/editload", "[Filename] - Load .schematic into clipboard"); commands.put("/editsave", "[Filename] - Save clipboard to .schematic"); commands.put("/editfill", "[ID] [Radius] - Fill a hole"); + commands.put("/editdrain", "[Radius] - Drain nearby water/lava pools"); commands.put("/editscript", "[Filename] - Run a WorldEdit script"); commands.put("/editlimit", "[Num] - See documentation"); commands.put("/unstuck", "Go up to the first free spot"); @@ -573,6 +574,15 @@ public class WorldEdit extends Plugin { return true; + // Drain pools + } else if(split[0].equalsIgnoreCase("/editdrain")) { + checkArgs(split, 1, 1, split[0]); + int radius = Math.max(0, Integer.parseInt(split[1])); + int affected = editSession.drainArea(player.getBlockIn(), radius); + player.print(affected + " block(s) have been changed."); + + return true; + // Replace all blocks in the region } else if(split[0].equalsIgnoreCase("/editreplace")) { checkArgs(split, 1, 2, split[0]); diff --git a/src/com/sk89q/worldedit/BlockPoint.java b/src/com/sk89q/worldedit/BlockPoint.java new file mode 100644 index 000000000..dcf9f3873 --- /dev/null +++ b/src/com/sk89q/worldedit/BlockPoint.java @@ -0,0 +1,65 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * 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 . +*/ + +package com.sk89q.worldedit; + +/** + * Extension of Point that supports being compared as ints (for accuracy). + * + * @author sk89q + */ +public class BlockPoint extends Point { + /** + * Construct the Point object. + * + * @param pt + */ + public BlockPoint(Point pt) { + super(pt); + } + + /** + * Checks if another object is equivalent. + * + * @param obj + * @return whether the other object is equivalent + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Point)) { + return false; + } + Point other = (Point)obj; + return (int)other.x == (int)this.x && (int)other.y == (int)this.y + && (int)other.z == (int)this.z; + + } + + /** + * Gets the hash code. + * + * @return hash code + */ + @Override + public int hashCode() { + return (Integer.valueOf((int)x).hashCode() >> 13) ^ + (Integer.valueOf((int)y).hashCode() >> 7) ^ + Integer.valueOf((int)z).hashCode(); + } +} diff --git a/src/com/sk89q/worldedit/Point.java b/src/com/sk89q/worldedit/Point.java index 214f80f46..2401b07cd 100644 --- a/src/com/sk89q/worldedit/Point.java +++ b/src/com/sk89q/worldedit/Point.java @@ -23,8 +23,8 @@ package com.sk89q.worldedit; * * @author Albert */ -public final class Point { - private final double x, y, z; +public class Point { + protected final double x, y, z; /** * Construct the Point object. @@ -65,6 +65,17 @@ public final class Point { this.z = (double)z; } + /** + * Construct the Point object. + * + * @param pt + */ + public Point(Point pt) { + this.x = pt.x; + this.y = pt.y; + this.z = pt.z; + } + /** * Construct the Point object. */ @@ -303,6 +314,18 @@ public final class Point { return new Point(this.x / x, this.y / y, this.z / z); } + /** + * Get the distance away from a point. + * + * @param pt + * @return distance + */ + public double distance(Point pt) { + return Math.sqrt(Math.pow(pt.x - x, 2) + + Math.pow(pt.y - y, 2) + + Math.pow(pt.z - z, 2)); + } + /** * Get a block point from a point. * @@ -344,4 +367,14 @@ public final class Point { ((new Double(y)).hashCode() >> 7) ^ (new Double(z)).hashCode(); } + + /** + * Returns string representation "(x, y, z)". + * + * @return string + */ + @Override + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } }