Added /editexpand and /editcontract.

This commit is contained in:
sk89q 2010-10-12 21:41:06 -07:00
parent 68dcce31f8
commit 6ab19fd52d
9 changed files with 342 additions and 45 deletions

View File

@ -584,15 +584,13 @@ public class EditSession {
* Stack a cuboid region.
*
* @param region
* @param xm
* @param ym
* @param zm
* @param dir
* @param count
* @param copyAir
* @return number of blocks affected
* @throws MaxChangedBlocksException
*/
public int stackCuboidRegion(Region region, int xm, int ym, int zm,
public int stackCuboidRegion(Region region, Vector dir,
int count, boolean copyAir)
throws MaxChangedBlocksException {
int affected = 0;
@ -610,8 +608,8 @@ public class EditSession {
if (blockType != 0 || copyAir) {
for (int i = 1; i <= count; i++) {
if (setBlock(x + xs * xm * i, y + ys * ym * i,
z + zs * zm * i, blockType)) {
if (setBlock(x + xs * dir.getBlockX() * i, y + ys * dir.getBlockY() * i,
z + zs * dir.getBlockZ() * i, blockType)) {
affected++;
}
}

View File

@ -91,6 +91,8 @@ public class WorldEdit {
commands.put("/editfill", "[ID] [Radius] <Depth> - Fill a hole");
commands.put("/editdrain", "[Radius] - Drain nearby water/lava pools");
commands.put("/editlimit", "[Num] - See documentation");
commands.put("/editexpand", "<Dir> [Num] - Expands the selection");
commands.put("/editcontract", "<Dir> [Num] - Contracts the selection");
commands.put("/unstuck", "Go up to the first free spot");
}
@ -464,49 +466,101 @@ public class WorldEdit {
split[0].equalsIgnoreCase("/editstack")) {
checkArgs(split, 0, 2, split[0]);
int count = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 1;
String dir = split.length > 2 ? split[2].toLowerCase() : "me";
int xm = 0;
int ym = 0;
int zm = 0;
Vector dir = getDirection(player,
split.length > 2 ? split[2].toLowerCase() : "me");
boolean copyAir = split[0].equalsIgnoreCase("/editstackair");
if (dir.equals("me")) {
// From hey0's code
double rot = (player.getYaw() - 90) % 360;
if (rot < 0) {
rot += 360.0;
}
dir = etc.getCompassPointForDirection(rot).toLowerCase();
}
if (dir.charAt(0) == 'w') {
zm += 1;
} else if (dir.charAt(0) == 'e') {
zm -= 1;
} else if (dir.charAt(0) == 's') {
xm += 1;
} else if (dir.charAt(0) == 'n') {
xm -= 1;
} else if (dir.charAt(0) == 'u') {
ym += 1;
} else if (dir.charAt(0) == 'd') {
ym -= 1;
} else {
player.printError("Unknown direction: " + dir);
return true;
}
int affected = editSession.stackCuboidRegion(session.getRegion(),
xm, ym, zm, count, copyAir);
dir, count, copyAir);
player.print(affected + " blocks changed. Undo with /editundo");
return true;
// Expand
} else if (split[0].equalsIgnoreCase("/editexpand")) {
checkArgs(split, 1, 2, split[0]);
Vector dir;
int change;
if (split.length == 3) {
dir = getDirection(player, split[1].toLowerCase());
change = Integer.parseInt(split[2]);
} else {
dir = getDirection(player, "me");
change = Integer.parseInt(split[1]);
}
Region region = session.getRegion();
int oldSize = region.getSize();
region.expand(dir.multiply(change));
session.learnRegionChanges();
int newSize = region.getSize();
player.print("Region expanded " + (newSize - oldSize) + " blocks.");
return true;
// Expand
} else if (split[0].equalsIgnoreCase("/editcontract")) {
checkArgs(split, 1, 2, split[0]);
Vector dir;
int change;
if (split.length == 3) {
dir = getDirection(player, split[1].toLowerCase());
change = Integer.parseInt(split[2]);
} else {
dir = getDirection(player, "me");
change = Integer.parseInt(split[1]);
}
Region region = session.getRegion();
int oldSize = region.getSize();
region.contract(dir.multiply(change));
session.learnRegionChanges();
int newSize = region.getSize();
player.print("Region contracted " + (oldSize - newSize) + " blocks.");
return true;
}
return false;
}
/**
* Get the direction vector for a player's direction. May return
* null if a direction could not be found.
*
* @param player
* @param dir
* @return
*/
public Vector getDirection(WorldEditPlayer player, String dir)
throws UnknownDirectionException {
int xm = 0;
int ym = 0;
int zm = 0;
if (dir.equals("me")) {
dir = player.getCardinalDirection();
}
if (dir.charAt(0) == 'w') {
zm += 1;
} else if (dir.charAt(0) == 'e') {
zm -= 1;
} else if (dir.charAt(0) == 's') {
xm += 1;
} else if (dir.charAt(0) == 'n') {
xm -= 1;
} else if (dir.charAt(0) == 'u') {
ym += 1;
} else if (dir.charAt(0) == 'd') {
ym -= 1;
} else {
throw new UnknownDirectionException(dir);
}
return new Vector(xm, ym, zm);
}
/**
* Remove a session.
*

View File

@ -98,6 +98,21 @@ public class WorldEditPlayer {
return player.getItemInHand();
}
/**
* Get the player's cardinal direction (N, W, NW, etc.).
*
* @return
*/
public String getCardinalDirection() {
// From hey0's code
double rot = (getYaw() - 90) % 360;
if (rot < 0) {
rot += 360.0;
}
return etc.getCompassPointForDirection(rot).toLowerCase();
}
/**
* Print a WorldEdit message.
*

View File

@ -157,6 +157,8 @@ public class WorldEditSMListener extends PluginListener {
} catch (MaxChangedBlocksException e5) {
modPlayer.sendMessage(Colors.Rose + "The maximum number of blocks changed ("
+ e5.getBlockLimit() + ") in an instance was reached.");
} catch (UnknownDirectionException ue) {
modPlayer.sendMessage(Colors.Rose + "Unknown direction: " + ue.getDirection());
} catch (InsufficientArgumentsException e6) {
modPlayer.sendMessage(Colors.Rose + e6.getMessage());
} catch (WorldEditException e7) {

View File

@ -27,6 +27,7 @@ import java.util.LinkedList;
public class WorldEditSession {
public static final int MAX_HISTORY_SIZE = 15;
private Vector pos1, pos2;
private Region region;
private LinkedList<EditSession> history = new LinkedList<EditSession>();
private int historyPointer = 0;
private CuboidClipboard clipboard;
@ -132,6 +133,9 @@ public class WorldEditSession {
*/
public void setPos1(Vector pt) {
pos1 = pt;
if (pos1 != null && pos2 != null) {
region = new CuboidRegion(pos1, pos2);
}
}
/**
@ -152,19 +156,31 @@ public class WorldEditSession {
*/
public void setPos2(Vector pt) {
pos2 = pt;
if (pos1 != null && pos2 != null) {
region = new CuboidRegion(pos1, pos2);
}
}
/**
* Get the region.
* Update session position 1/2 based on the currently set region,
* provided that the region is of a cuboid.
*/
public void learnRegionChanges() {
if (region instanceof CuboidRegion) {
CuboidRegion cuboidRegion = (CuboidRegion)region;
pos1 = cuboidRegion.getPos1();
pos2 = cuboidRegion.getPos2();
}
}
/**
* Get the region. May return null. If you change the region, you should
* call learnRegionChanges().
*
* @return region
* @throws IncompleteRegionException
*/
public Region getRegion() throws IncompleteRegionException {
checkPos1();
checkPos2();
return new CuboidRegion(pos1, pos2);
public Region getRegion() {
return region;
}
/**

View File

@ -120,6 +120,140 @@ public class CuboidRegion implements Region {
return (int)(max.getZ() - min.getZ() + 1);
}
/**
* Expands the cuboid in a direction.
*
* @param change
*/
public void expand(Vector change) {
if (change.getX() > 0) {
if (Math.max(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
} else {
if (Math.min(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
}
if (change.getY() > 0) {
if (Math.max(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
} else {
if (Math.min(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
}
if (change.getZ() > 0) {
if (Math.max(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
} else {
if (Math.min(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
}
}
/**
* Contracts the cuboid in a direction.
*
* @param change
*/
public void contract(Vector change) {
if (change.getX() < 0) {
if (Math.max(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
} else {
if (Math.min(pos1.getX(), pos2.getX()) == pos1.getX()) {
pos1 = pos1.add(new Vector(change.getX(), 0, 0));
} else {
pos2 = pos2.add(new Vector(change.getX(), 0, 0));
}
}
if (change.getY() < 0) {
if (Math.max(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
} else {
if (Math.min(pos1.getY(), pos2.getY()) == pos1.getY()) {
pos1 = pos1.add(new Vector(0, change.getY(), 0));
} else {
pos2 = pos2.add(new Vector(0, change.getY(), 0));
}
}
if (change.getZ() < 0) {
if (Math.max(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
} else {
if (Math.min(pos1.getZ(), pos2.getZ()) == pos1.getZ()) {
pos1 = pos1.add(new Vector(0, 0, change.getZ()));
} else {
pos2 = pos2.add(new Vector(0, 0, change.getZ()));
}
}
}
/**
* Get position 1.
*
* @return position 1
*/
public Vector getPos1() {
return pos1;
}
/**
* Set position 1.
*
* @param pos1
*/
public void setPos1(Vector pos1) {
this.pos1 = pos1;
}
/**
* Get position 2.
*
* @return position 2
*/
public Vector getPos2() {
return pos2;
}
/**
* Set position 2.
*
* @param pos2
*/
public void setPos2(Vector pos2) {
this.pos2 = pos2;
}
/**
* Get the iterator.
*

View File

@ -60,4 +60,16 @@ public interface Region extends Iterable<Vector> {
* @return length
*/
public int getLength();
/**
* Expand the region.
*
* @param change
*/
public void expand(Vector change);
/**
* Contract the region.
*
* @param change
*/
public void contract(Vector change);
}

View File

@ -0,0 +1,36 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit;
/**
*
* @author sk89q
*/
public class UnknownDirectionException extends WorldEditException {
private String dir;
public UnknownDirectionException(String dir) {
this.dir = dir;
}
public String getDirection() {
return dir;
}
}

View File

@ -280,6 +280,36 @@ public class Vector {
return new Vector(newX, newY, newZ);
}
/**
* Scalar multiplication.
*
* @param n
* @return New point
*/
public Vector multiply(double n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Scalar multiplication.
*
* @param n
* @return New point
*/
public Vector multiply(float n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Scalar multiplication.
*
* @param n
* @return New point
*/
public Vector multiply(int n) {
return new Vector(this.x * n, this.y * n, this.z * n);
}
/**
* Divide two points.
*