From bd9a90f01d63da67b6c72335427096a3be30c56e Mon Sep 17 00:00:00 2001 From: sk89q Date: Tue, 12 Oct 2010 22:38:05 -0700 Subject: [PATCH] Re-implemented /forestgen in Java. This version does not replace existing blocks. Undo system fixed. --- src/EditSession.java | 143 ++++++++++++++++++++++++++-- src/WorldEdit.java | 11 +++ src/com/sk89q/worldedit/Vector.java | 2 +- 3 files changed, 149 insertions(+), 7 deletions(-) diff --git a/src/EditSession.java b/src/EditSession.java index 9b56234fc..9309b6d4b 100644 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -130,19 +130,38 @@ public class EditSession { */ public boolean setBlock(Vector pt, int blockType) throws MaxChangedBlocksException { - if (!original.containsKey(pt)) { - original.put(pt.toBlockPoint(), getBlock(pt)); + BlockVector blockPt = pt.toBlockVector(); + + if (!original.containsKey(blockPt)) { + original.put(blockPt, getBlock(pt)); if (maxBlocks != -1 && original.size() > maxBlocks) { throw new MaxChangedBlocksException(maxBlocks); } } - current.put(pt.toBlockPoint(), blockType); + current.put(pt.toBlockVector(), blockType); return smartSetBlock(pt, blockType); } + /** + * Set a block only if there's no block already there. + * + * @param pt + * @param blockType + * @return if block was changed + * @throws MaxChangedBlocksException + */ + public boolean setBlockIfAir(Vector pt, int blockType) + throws MaxChangedBlocksException { + if (getBlock(pt) != 0) { + return false; + } else { + return setBlock(pt, blockType); + } + } + /** * Actually set the block. Will use queue. * @@ -154,7 +173,7 @@ public class EditSession { if (queued) { if (blockType != 0 && queuedBlocks.contains(blockType) && rawGetBlock(pt.add(0, -1, 0)) == 0) { - queue.put(pt.toBlockPoint(), blockType); + queue.put(pt.toBlockVector(), blockType); return getBlock(pt) != blockType; } else if (blockType == 0 && queuedBlocks.contains(rawGetBlock(pt.add(0, 1, 0)))) { @@ -175,8 +194,10 @@ public class EditSession { // In the case of the queue, the block may have not actually been // changed yet if (queued) { - if (current.containsKey(pt)) { - return current.get(pt); + BlockVector blockPt = pt.toBlockVector(); + + if (current.containsKey(blockPt)) { + return current.get(blockPt); } } return etc.getMCServer().e.a(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); @@ -684,4 +705,114 @@ public class EditSession { return affected; } + + + /** + * Set a block by chance. + * + * @param pos + * @param type + * @param c 0-1 chance + * @return whether a block was changed + */ + private boolean setChanceBlockIfAir(Vector pos, int type, double c) + throws MaxChangedBlocksException { + if (Math.random() <= c) { + return setBlockIfAir(pos, type); + } + return false; + } + + /** + * Makes a terrible looking pine tree. + * + * @param basePos + */ + private void makePineTree(Vector basePos) + throws MaxChangedBlocksException { + int trunkHeight = (int)Math.floor(Math.random() * 2) + 3; + int height = (int)Math.floor(Math.random() * 5) + 8; + + // Create trunk + for (int i = 0; i < trunkHeight; i++) { + if (!setBlockIfAir(basePos.add(0, i, 0), 17)) { + return; + } + } + + // Move up + basePos = basePos.add(0, trunkHeight, 0); + + int pos2[] = {-2, 2}; + + // Create tree + leaves + for (int i = 0; i < height; i++) { + setBlockIfAir(basePos.add(0, i, 0), 17); + + // Less leaves at these levels + double chance = ((i == 0 || i == height - 1) ? 0.6 : 1); + + // Inner leaves + setChanceBlockIfAir(basePos.add(-1, i, 0), 18, chance); + setChanceBlockIfAir(basePos.add(1, i, 0), 18, chance); + setChanceBlockIfAir(basePos.add(0, i, -1), 18, chance); + setChanceBlockIfAir(basePos.add(0, i, 1), 18, chance); + setChanceBlockIfAir(basePos.add(1, i, 1), 18, chance); + setChanceBlockIfAir(basePos.add(-1, i, 1), 18, chance); + setChanceBlockIfAir(basePos.add(1, i, -1), 18, chance); + setChanceBlockIfAir(basePos.add(-1, i, -1), 18, chance); + + if (!(i == 0 || i == height - 1)) { + for (int j = -2; j <= 2; j++) { + setChanceBlockIfAir(basePos.add(-2, i, j), 18, 0.6); + } + for (int j = -2; j <= 2; j++) { + setChanceBlockIfAir(basePos.add(2, i, j), 18, 0.6); + } + for (int j = -2; j <= 2; j++) { + setChanceBlockIfAir(basePos.add(j, i, -2), 18, 0.6); + } + for (int j = -2; j <= 2; j++) { + setChanceBlockIfAir(basePos.add(j, i, 2), 18, 0.6); + } + } + } + + setBlockIfAir(basePos.add(0, height, 0), 18); + } + + /** + * Makes a terrible looking pine forest. + * + * @param basePos + * @param size + * @return number of trees created + */ + public int makePineTreeForest(Vector basePos, int size) + throws MaxChangedBlocksException { + int affected = 0; + + for (int x = basePos.getBlockX() - size; x <= basePos.getBlockX() + size; x++) { + for (int z = basePos.getBlockZ() - size; z <= basePos.getBlockZ() + size; z++) { + // Don't want to be in the ground + if (getBlock(new Vector(x, basePos.getBlockY(), z)) != 0) { continue; } + // The gods don't want a tree here + if (Math.random() < 0.95) { continue; } + + for (int y = basePos.getBlockY(); y >= basePos.getBlockY() - 10; y--) { + // Check if we hit the ground + int t = getBlock(new Vector(x, y, z)); + if (t == 2 || t == 3) { + makePineTree(new Vector(x, y + 1, z)); + affected++; + break; + } else if (t != 0) { // Trees won't grow on this! + break; + } + } + } + } + + return affected; + } } diff --git a/src/WorldEdit.java b/src/WorldEdit.java index 4bb73689e..7e128224c 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -94,6 +94,7 @@ public class WorldEdit { commands.put("/editlimit", "[Num] - See documentation"); commands.put("/editexpand", " [Num] - Expands the selection"); commands.put("/editcontract", " [Num] - Contracts the selection"); + commands.put("/forestgen", " - Make an ugly pine tree forest"); commands.put("/unstuck", "Go up to the first free spot"); commands.put("/ascend", "Go up one level"); commands.put("/descend", "Go dowm one level"); @@ -495,6 +496,16 @@ public class WorldEdit { return true; + // Make pine tree forest + } else if (split[0].equalsIgnoreCase("/forestgen")) { + checkArgs(split, 0, 1, split[0]); + int size = split.length > 1 ? Math.max(1, Integer.parseInt(split[1])) : 10; + + int affected = editSession.makePineTreeForest(player.getPosition(), size); + player.print(affected + " pine trees created."); + + return true; + // Stack } else if (split[0].equalsIgnoreCase("/editstackair") || split[0].equalsIgnoreCase("/editstack")) { diff --git a/src/com/sk89q/worldedit/Vector.java b/src/com/sk89q/worldedit/Vector.java index 80d7f4120..de6a9cf2e 100644 --- a/src/com/sk89q/worldedit/Vector.java +++ b/src/com/sk89q/worldedit/Vector.java @@ -413,7 +413,7 @@ public class Vector { * * @return BlockVector */ - public BlockVector toBlockPoint() { + public BlockVector toBlockVector() { return new BlockVector(this); } }