diff --git a/src/RegionClipboard.java b/src/RegionClipboard.java index 5817a3c6c..da85eb60b 100644 --- a/src/RegionClipboard.java +++ b/src/RegionClipboard.java @@ -103,20 +103,36 @@ public class RegionClipboard { * @throws MaxChangedBlocksException */ public void paste(EditSession editSession, Point newOrigin, boolean noAir) - throws MaxChangedBlocksException { + throws MaxChangedBlocksException { + int offsetX = min.getX() - origin.getX() + newOrigin.getX(); + int offsetY = min.getY() - origin.getY() + newOrigin.getY(); + int offsetZ = min.getZ() - origin.getZ() + newOrigin.getZ(); + + place(editSession, offsetX, offsetY, offsetZ, noAir); + } + + /** + * Places the blocks in a position from the minimum corner. + * + * @param editSession + * @param offsetX + * @param offsetY + * @param offsetZ + * @param noAir + * @throws MaxChangedBlocksException + */ + public void place(EditSession editSession, int offsetX, + int offsetY, int offsetZ, boolean noAir) + throws MaxChangedBlocksException { int xs = getWidth(); int ys = getHeight(); int zs = getLength(); - int offsetX = min.getX() - origin.getX() + newOrigin.getX(); - int offsetY = min.getY() - origin.getY() + newOrigin.getY(); - int offsetZ = min.getZ() - origin.getZ() + newOrigin.getZ(); - for (int x = 0; x < xs; x++) { for (int y = 0; y < ys; y++) { for (int z = 0; z < zs; z++) { if (noAir && data[x][y][z] == 0) { continue; } - + editSession.setBlock(x + offsetX, y + offsetY, z + offsetZ, data[x][y][z]); } @@ -124,6 +140,40 @@ public class RegionClipboard { } } + /** + * Stack the clipboard in a certain direction a certain number of + * times. + * + * @param editSession + * @param xm + * @param ym + * @param zm + * @short count + * @param noAir + * @param moveOrigin move the origin + * @throws MaxChangedBlocksException + */ + public void stack(EditSession editSession, int xm, int ym, int zm, short count, + boolean noAir, boolean moveOrigin) throws MaxChangedBlocksException { + int xs = getWidth(); + int ys = getHeight(); + int zs = getLength(); + int offsetX = min.getX(); + int offsetY = min.getY(); + int offsetZ = min.getZ(); + + for (short i = 1; i <= count; i++) { + place(editSession, offsetX + xm * xs, offsetY + ym * ys, + offsetZ + zm * zs, noAir); + } + + if (moveOrigin) { + min = new Point(offsetX + xm * count, + offsetY + ym * count, + offsetZ + zm * count); + } + } + /** * Saves the clipboard data to a .schematic-format file. * diff --git a/src/WorldEdit.java b/src/WorldEdit.java index 265c3e175..c537835b1 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -65,6 +65,8 @@ public class WorldEdit extends Plugin { commands.put("/editcopy", "Copies the currently selected region"); commands.put("/editpaste", "Pastes the clipboard"); commands.put("/editpasteair", "Pastes the clipboard (with air)"); + commands.put("/editstack [Dir] ", "Stacks the clipboard"); + commands.put("/editstackair [Dir] ", "Stacks the clipboard (with air)"); commands.put("/editload", "[Filename] - Load .schematic into clipboard"); commands.put("/editsave", "[Filename] - Save clipboard to .schematic"); commands.put("/editfill", "[ID] [Radius] - Fill a hole"); @@ -715,6 +717,74 @@ public class WorldEdit extends Plugin { logger.log(Level.INFO, player.getName() + " used " + split[0]); player.sendMessage(Colors.LightPurple + "Block(s) copied."); + return true; + + // Stack + } else if (split[0].equalsIgnoreCase("/editstackair") || + split[0].equalsIgnoreCase("/editstack")) { + checkArgs(split, 1, 2, split[0]); + String dir = split[1]; + int count = Math.max(1, Integer.parseInt(split[2])); + int xm = 0; + int ym = 0; + int zm = 0; + boolean copyAir = split[0].equalsIgnoreCase("/editstackair"); + + if (dir.equalsIgnoreCase("me")) { + dir = etc.getCompassPointForDirection(player.getRotation()); + } + + if (dir.equalsIgnoreCase("w")) { + zm += 1; + } else if (dir.equalsIgnoreCase("e")) { + zm -= 1; + } else if (dir.equalsIgnoreCase("s")) { + xm += 1; + } else if (dir.equalsIgnoreCase("n")) { + xm -= 1; + } else if (dir.equalsIgnoreCase("u")) { + ym += 1; + } else if (dir.equalsIgnoreCase("d")) { + ym -= 1; + } else { + player.sendMessage(Colors.Rose + "Unknown direction: " + dir); + return true; + } + + int xs = session.getWidth(); + int ys = session.getHeight(); + int zs = session.getLength(); + + int affected = 0; + + for (int x = lowerX; x <= upperX; x++) { + for (int z = lowerZ; z <= upperZ; z++) { + for (int y = lowerY; y <= lowerY; y++) { + int blockType = editSession.getBlock(x, y, z); + + if (blockType != 0 || copyAir) { + for (int i = 1; i <= count; i++) { + editSession.setBlock(x + xs * xm * i, y + ys * ym * i, + z + zs * zm * i, blockType); + affected++; + } + } + } + } + } + + int shiftX = xs * xm * count; + int shiftY = ys * ym * count; + int shiftZ = zs * zm * count; + + int[] pos1 = session.getPos1(); + int[] pos2 = session.getPos2(); + session.setPos1(pos1[0] + shiftX, pos1[1] + shiftY, pos1[2] + shiftZ); + session.setPos2(pos2[0] + shiftX, pos2[1] + shiftY, pos2[2] + shiftZ); + + logger.log(Level.INFO, player.getName() + " used " + split[0]); + player.sendMessage(Colors.LightPurple + "Stacked. Undo with /editundo"); + return true; } diff --git a/src/WorldEditSession.java b/src/WorldEditSession.java index b7625f6ab..36d8e87a0 100644 --- a/src/WorldEditSession.java +++ b/src/WorldEditSession.java @@ -273,6 +273,36 @@ public class WorldEditSession { (getUpperZ() - getLowerZ() + 1); } + /** + * Get the width (X-direction) of the selected region. + * + * @return + * @throws IncompleteRegionException + */ + public int getWidth() throws IncompleteRegionException { + return getUpperX() - getLowerX() + 1; + } + + /** + * Get the length (Z-direction) of the selected region. + * + * @return + * @throws IncompleteRegionException + */ + public int getLength() throws IncompleteRegionException { + return getUpperY() - getLowerY() + 1; + } + + /** + * Get the height (Y-direction) of the selected region. + * + * @return + * @throws IncompleteRegionException + */ + public int getHeight() throws IncompleteRegionException { + return getUpperZ() - getLowerZ() + 1; + } + /** * Gets the clipboard. *