Added pyramid generation with /pyramid & /hpyramid

This commit is contained in:
hretsam 2011-08-07 02:40:48 +02:00
parent 2068189cf5
commit 2342acfae2
3 changed files with 157 additions and 47 deletions

View File

@ -16,7 +16,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit; package com.sk89q.worldedit;
import java.util.Map; import java.util.Map;
@ -47,39 +46,38 @@ import com.sk89q.worldedit.patterns.*;
* @author sk89q * @author sk89q
*/ */
public class EditSession { public class EditSession {
/** /**
* Random number generator. * Random number generator.
*/ */
private static Random prng = new Random(); private static Random prng = new Random();
/** /**
* World. * World.
*/ */
protected LocalWorld world; protected LocalWorld world;
/** /**
* Stores the original blocks before modification. * Stores the original blocks before modification.
*/ */
private DoubleArrayList<BlockVector, BaseBlock> original = private DoubleArrayList<BlockVector, BaseBlock> original =
new DoubleArrayList<BlockVector, BaseBlock>( new DoubleArrayList<BlockVector, BaseBlock>(
true); true);
/** /**
* Stores the current blocks. * Stores the current blocks.
*/ */
private DoubleArrayList<BlockVector, BaseBlock> current = private DoubleArrayList<BlockVector, BaseBlock> current =
new DoubleArrayList<BlockVector, BaseBlock>( new DoubleArrayList<BlockVector, BaseBlock>(
false); false);
/** /**
* Blocks that should be placed before last. * Blocks that should be placed before last.
*/ */
private DoubleArrayList<BlockVector, BaseBlock> queueAfter = private DoubleArrayList<BlockVector, BaseBlock> queueAfter =
new DoubleArrayList<BlockVector, BaseBlock>( new DoubleArrayList<BlockVector, BaseBlock>(
false); false);
/** /**
* Blocks that should be placed last. * Blocks that should be placed last.
*/ */
private DoubleArrayList<BlockVector, BaseBlock> queueLast = private DoubleArrayList<BlockVector, BaseBlock> queueLast =
new DoubleArrayList<BlockVector, BaseBlock>( new DoubleArrayList<BlockVector, BaseBlock>(
false); false);
/** /**
@ -158,28 +156,28 @@ public class EditSession {
public boolean rawSetBlock(Vector pt, BaseBlock block) { public boolean rawSetBlock(Vector pt, BaseBlock block) {
int y = pt.getBlockY(); int y = pt.getBlockY();
int type = block.getType(); int type = block.getType();
if (y < 0 || y > 127) { if (y < 0 || y > 127) {
return false; return false;
} }
// No invalid blocks // No invalid blocks
if (!world.isValidBlockType(type)) { if (!world.isValidBlockType(type)) {
return false; return false;
} }
if (mask != null) { if (mask != null) {
if (!mask.matches(this, pt)) { if (!mask.matches(this, pt)) {
return false; return false;
} }
} }
int existing = world.getBlockType(pt); int existing = world.getBlockType(pt);
// Clear the container block so that it doesn't drop items // Clear the container block so that it doesn't drop items
if (BlockType.isContainerBlock(existing) && blockBag == null) { if (BlockType.isContainerBlock(existing) && blockBag == null) {
world.clearContainerBlockContents(pt); world.clearContainerBlockContents(pt);
// Ice turns until water so this has to be done first // Ice turns until water so this has to be done first
} else if (existing == BlockID.ICE) { } else if (existing == BlockID.ICE) {
world.setBlockType(pt, 0); world.setBlockType(pt, 0);
} }
@ -205,7 +203,7 @@ public class EditSession {
} }
} }
} }
boolean result; boolean result;
if (BlockType.usesData(id)) { if (BlockType.usesData(id)) {
@ -222,30 +220,30 @@ public class EditSession {
} }
} }
//System.out.println(pt + "" +result); //System.out.println(pt + "" +result);
if (id != 0) { if (id != 0) {
// Signs // Signs
if (block instanceof SignBlock) { if (block instanceof SignBlock) {
SignBlock signBlock = (SignBlock) block; SignBlock signBlock = (SignBlock) block;
world.copyToWorld(pt, signBlock); world.copyToWorld(pt, signBlock);
// Chests // Chests
} else if (block instanceof ChestBlock && blockBag == null) { } else if (block instanceof ChestBlock && blockBag == null) {
ChestBlock chestBlock = (ChestBlock) block; ChestBlock chestBlock = (ChestBlock) block;
world.copyToWorld(pt, chestBlock); world.copyToWorld(pt, chestBlock);
// Furnaces // Furnaces
} else if (block instanceof FurnaceBlock && blockBag == null) { } else if (block instanceof FurnaceBlock && blockBag == null) {
FurnaceBlock furnaceBlock = (FurnaceBlock) block; FurnaceBlock furnaceBlock = (FurnaceBlock) block;
world.copyToWorld(pt, furnaceBlock); world.copyToWorld(pt, furnaceBlock);
// Dispenser // Dispenser
} else if (block instanceof DispenserBlock && blockBag == null) { } else if (block instanceof DispenserBlock && blockBag == null) {
DispenserBlock dispenserBlock = (DispenserBlock) block; DispenserBlock dispenserBlock = (DispenserBlock) block;
world.copyToWorld(pt, dispenserBlock); world.copyToWorld(pt, dispenserBlock);
// Mob spawners // Mob spawners
} else if (block instanceof MobSpawnerBlock) { } else if (block instanceof MobSpawnerBlock) {
MobSpawnerBlock mobSpawnerblock = (MobSpawnerBlock) block; MobSpawnerBlock mobSpawnerblock = (MobSpawnerBlock) block;
world.copyToWorld(pt, mobSpawnerblock); world.copyToWorld(pt, mobSpawnerblock);
// Note blocks // Note blocks
} else if (block instanceof NoteBlock) { } else if (block instanceof NoteBlock) {
NoteBlock noteBlock = (NoteBlock) block; NoteBlock noteBlock = (NoteBlock) block;
world.copyToWorld(pt, noteBlock); world.copyToWorld(pt, noteBlock);
@ -337,14 +335,14 @@ public class EditSession {
// Place torches, etc. last // Place torches, etc. last
if (BlockType.shouldPlaceLast(block.getType())) { if (BlockType.shouldPlaceLast(block.getType())) {
queueLast.put(pt.toBlockVector(), block); queueLast.put(pt.toBlockVector(), block);
return !(getBlockType(pt) == block.getType() return !(getBlockType(pt) == block.getType()
&& getBlockData(pt) == block.getData()); && getBlockData(pt) == block.getData());
// Destroy torches, etc. first // Destroy torches, etc. first
} else if (BlockType.shouldPlaceLast(getBlockType(pt))) { } else if (BlockType.shouldPlaceLast(getBlockType(pt))) {
rawSetBlock(pt, new BaseBlock(0)); rawSetBlock(pt, new BaseBlock(0));
} else { } else {
queueAfter.put(pt.toBlockVector(), block); queueAfter.put(pt.toBlockVector(), block);
return !(getBlockType(pt) == block.getType() return !(getBlockType(pt) == block.getType()
&& getBlockData(pt) == block.getData()); && getBlockData(pt) == block.getData());
} }
} }
@ -393,7 +391,7 @@ public class EditSession {
return world.getBlockType(pt); return world.getBlockType(pt);
} }
public int getBlockData(Vector pt) { public int getBlockData(Vector pt) {
// In the case of the queue, the block may have not actually been // In the case of the queue, the block may have not actually been
// changed yet // changed yet
@ -423,27 +421,27 @@ public class EditSession {
SignBlock block = new SignBlock(type, data); SignBlock block = new SignBlock(type, data);
world.copyFromWorld(pt, block); world.copyFromWorld(pt, block);
return block; return block;
// Chest // Chest
} else if (type == BlockID.CHEST) { } else if (type == BlockID.CHEST) {
ChestBlock block = new ChestBlock(data); ChestBlock block = new ChestBlock(data);
world.copyFromWorld(pt, block); world.copyFromWorld(pt, block);
return block; return block;
// Furnace // Furnace
} else if (type == BlockID.FURNACE || type == BlockID.BURNING_FURNACE) { } else if (type == BlockID.FURNACE || type == BlockID.BURNING_FURNACE) {
FurnaceBlock block = new FurnaceBlock(type, data); FurnaceBlock block = new FurnaceBlock(type, data);
world.copyFromWorld(pt, block); world.copyFromWorld(pt, block);
return block; return block;
// Dispenser // Dispenser
} else if (type == BlockID.DISPENSER) { } else if (type == BlockID.DISPENSER) {
DispenserBlock block = new DispenserBlock(data); DispenserBlock block = new DispenserBlock(data);
world.copyFromWorld(pt, block); world.copyFromWorld(pt, block);
return block; return block;
// Mob spawner // Mob spawner
} else if (type == BlockID.MOB_SPAWNER) { } else if (type == BlockID.MOB_SPAWNER) {
MobSpawnerBlock block = new MobSpawnerBlock(data); MobSpawnerBlock block = new MobSpawnerBlock(data);
world.copyFromWorld(pt, block); world.copyFromWorld(pt, block);
return block; return block;
// Note block // Note block
} else if (type == BlockID.NOTE_BLOCK) { } else if (type == BlockID.NOTE_BLOCK) {
NoteBlock block = new NoteBlock(data); NoteBlock block = new NoteBlock(data);
world.copyFromWorld(pt, block); world.copyFromWorld(pt, block);
@ -536,7 +534,7 @@ public class EditSession {
} }
queued = false; queued = false;
} }
/** /**
* Set fast mode. * Set fast mode.
* *
@ -545,7 +543,7 @@ public class EditSession {
public void setFastMode(boolean fastMode) { public void setFastMode(boolean fastMode) {
this.fastMode = fastMode; this.fastMode = fastMode;
} }
/** /**
* Return fast mode status. * Return fast mode status.
* *
@ -1603,7 +1601,7 @@ public class EditSession {
if (setBlock(cur, stationaryBlock)){ if (setBlock(cur, stationaryBlock)){
++affected; ++affected;
} }
// Check radius // Check radius
if (pos.distance(cur) > radius) { if (pos.distance(cur) > radius) {
continue; continue;
@ -1851,6 +1849,49 @@ public class EditSession {
return affected; return affected;
} }
/**
* Makes a pyramid.
*
* @param pos
* @param block
* @param size
* @param filled
* @return number of blocks changed
* @throws MaxChangedBlocksException
*/
public int makePyramid(Vector pos, Pattern block, int size,
boolean filled) throws MaxChangedBlocksException {
int affected = 0;
int height = size;
for (int y = 0; y <= height; ++y) {
size--;
for (int x = 0; x <= size; ++x) {
for (int z = 0; z <= size; ++z) {
if ((filled && z <= size && x <= size) || z == size || x == size) {
if (setBlock(pos.add(x, y, z), block)) {
++affected;
}
if (setBlock(pos.add(-x, y, z), block)) {
++affected;
}
if (setBlock(pos.add(x, y, -z), block)) {
++affected;
}
if (setBlock(pos.add(-x, y, -z), block)) {
++affected;
}
}
}
}
}
return affected;
}
/** /**
* Thaw. * Thaw.
* *
@ -1944,7 +1985,7 @@ public class EditSession {
|| id == 55 // Redstone wire || id == 55 // Redstone wire
|| id == 59 // Crops || id == 59 // Crops
|| (id >= 63 && id <= 72) || id == 75 // Redstone || (id >= 63 && id <= 72) || id == 75 // Redstone
// torch // torch
|| id == 76 // Redstone torch || id == 76 // Redstone torch
|| id == 77 // Stone button || id == 77 // Stone button
|| id == 78 // Snow || id == 78 // Snow
@ -2026,9 +2067,9 @@ public class EditSession {
*/ */
private void makePumpkinPatchVine(Vector basePos, Vector pos) private void makePumpkinPatchVine(Vector basePos, Vector pos)
throws MaxChangedBlocksException { throws MaxChangedBlocksException {
if (pos.distance(basePos) > 4) if (pos.distance(basePos) > 4)
return; return;
if (getBlockType(pos) != 0) if (getBlockType(pos) != 0)
return; return;
for (int i = -1; i > -3; --i) { for (int i = -1; i > -3; --i) {
@ -2046,27 +2087,27 @@ public class EditSession {
int h = prng.nextInt(3) - 1; int h = prng.nextInt(3) - 1;
if (t == 0) { if (t == 0) {
if (prng.nextBoolean()) if (prng.nextBoolean())
makePumpkinPatchVine(basePos, pos.add(1, 0, 0)); makePumpkinPatchVine(basePos, pos.add(1, 0, 0));
if (prng.nextBoolean()) if (prng.nextBoolean())
setBlockIfAir(pos.add(1, h, -1), new BaseBlock(18)); setBlockIfAir(pos.add(1, h, -1), new BaseBlock(18));
setBlockIfAir(pos.add(0, 0, -1), new BaseBlock(86)); setBlockIfAir(pos.add(0, 0, -1), new BaseBlock(86));
} else if (t == 1) { } else if (t == 1) {
if (prng.nextBoolean()) if (prng.nextBoolean())
makePumpkinPatchVine(basePos, pos.add(0, 0, 1)); makePumpkinPatchVine(basePos, pos.add(0, 0, 1));
if (prng.nextBoolean()) if (prng.nextBoolean())
setBlockIfAir(pos.add(1, h, 0), new BaseBlock(18)); setBlockIfAir(pos.add(1, h, 0), new BaseBlock(18));
setBlockIfAir(pos.add(1, 0, 1), new BaseBlock(86)); setBlockIfAir(pos.add(1, 0, 1), new BaseBlock(86));
} else if (t == 2) { } else if (t == 2) {
if (prng.nextBoolean()) if (prng.nextBoolean())
makePumpkinPatchVine(basePos, pos.add(0, 0, -1)); makePumpkinPatchVine(basePos, pos.add(0, 0, -1));
if (prng.nextBoolean()) if (prng.nextBoolean())
setBlockIfAir(pos.add(-1, h, 0), new BaseBlock(18)); setBlockIfAir(pos.add(-1, h, 0), new BaseBlock(18));
setBlockIfAir(pos.add(-1, 0, 1), new BaseBlock(86)); setBlockIfAir(pos.add(-1, 0, 1), new BaseBlock(86));
} else if (t == 3) { } else if (t == 3) {
if (prng.nextBoolean()) if (prng.nextBoolean())
makePumpkinPatchVine(basePos, pos.add(-1, 0, 0)); makePumpkinPatchVine(basePos, pos.add(-1, 0, 0));
if (prng.nextBoolean()) if (prng.nextBoolean())
setBlockIfAir(pos.add(-1, h, -1), new BaseBlock(18)); setBlockIfAir(pos.add(-1, h, -1), new BaseBlock(18));
setBlockIfAir(pos.add(-1, 0, -1), new BaseBlock(86)); setBlockIfAir(pos.add(-1, 0, -1), new BaseBlock(86));
} }
@ -2089,7 +2130,7 @@ public class EditSession {
for (int z = basePos.getBlockZ() - size; z <= basePos.getBlockZ() for (int z = basePos.getBlockZ() - size; z <= basePos.getBlockZ()
+ size; ++z) { + size; ++z) {
// Don't want to be in the ground // Don't want to be in the ground
if (!getBlock(new Vector(x, basePos.getBlockY(), z)).isAir()) if (!getBlock(new Vector(x, basePos.getBlockY(), z)).isAir())
continue; continue;
// The gods don't want a pumpkin patch here // The gods don't want a pumpkin patch here
if (Math.random() < 0.98) { if (Math.random() < 0.98) {
@ -2270,7 +2311,6 @@ public class EditSession {
* maximal height * maximal height
* @return height of highest block found or 'minY' * @return height of highest block found or 'minY'
*/ */
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) { public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
for (int y = maxY; y >= minY; --y) { for (int y = maxY; y >= minY; --y) {
Vector pt = new Vector(x, y, z); Vector pt = new Vector(x, y, z);
@ -2327,7 +2367,7 @@ public class EditSession {
public void setBlockBag(BlockBag blockBag) { public void setBlockBag(BlockBag blockBag) {
this.blockBag = blockBag; this.blockBag = blockBag;
} }
/** /**
* Get the world. * Get the world.
* *
@ -2336,7 +2376,7 @@ public class EditSession {
public LocalWorld getWorld() { public LocalWorld getWorld() {
return world; return world;
} }
/** /**
* Get the number of blocks changed, including repeated block changes. * Get the number of blocks changed, including repeated block changes.
* *

View File

@ -178,4 +178,48 @@ public class GenerationCommands {
int affected = editSession.makePumpkinPatches(player.getPosition(), size); int affected = editSession.makePumpkinPatches(player.getPosition(), size);
player.print(affected + " pumpkin patches created."); player.print(affected + " pumpkin patches created.");
} }
@Command(
aliases = {"/pyramid"},
usage = "<block> <range>",
desc = "Generate a filled pyramid",
min = 2,
max = 2
)
@CommandPermissions({"worldedit.generation.pyramid"})
public static void pyramid(CommandContext args, WorldEdit we,
LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0));
int size = Math.max(1, args.getInteger(1));
Vector pos = session.getPlacementPosition(player);
int affected = editSession.makePyramid(pos, block, size, true);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
@Command(
aliases = {"/hpyramid"},
usage = "<block> <range>",
desc = "Generate a hollow pyramid",
min = 2,
max = 2
)
@CommandPermissions({"worldedit.generation.pyramid"})
public static void hpyramid(CommandContext args, WorldEdit we,
LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0));
int size = Math.max(1, args.getInteger(1));
Vector pos = session.getPlacementPosition(player);
int affected = editSession.makePyramid(pos, block, size, false);
player.findFreePosition();
player.print(affected + " block(s) have been created.");
}
} }

View File

@ -50,10 +50,19 @@ commands:
description: Modify block change limit description: Modify block change limit
usage: /<command> <limit> usage: /<command> <limit>
permissions: 'worldedit.limit' permissions: 'worldedit.limit'
/gmask:
description: Set the global mask
usage: /<command> [mask]
aliases: ['gmask']
permissions: 'worldedit.global-mask'
we: we:
description: WorldEdit commands description: WorldEdit commands
usage: /<command> usage: /<command>
aliases: ['worldedit'] aliases: ['worldedit']
/fast:
description: Toggle fast mode
usage: /<command>
permissions: 'worldedit.fast'
toggleplace: toggleplace:
description: description:
usage: /<command> usage: /<command>
@ -85,6 +94,10 @@ commands:
description: Generate pumpkin patches description: Generate pumpkin patches
usage: /<command> [size] usage: /<command> [size]
permissions: 'worldedit.generation.pumpkins' permissions: 'worldedit.generation.pumpkins'
/pyramid:
description: Generate a filled pyramid
usage: /<command> <block> <range> <height> [inverted]
permissions: 'worldedit.generation.sphere'
/undo: /undo:
description: Undoes the last action description: Undoes the last action
usage: /<command> [times] usage: /<command> [times]
@ -105,11 +118,11 @@ commands:
permissions: 'worldedit.navigation.unstuck' permissions: 'worldedit.navigation.unstuck'
ascend: ascend:
description: Go up a floor description: Go up a floor
usage: /<command> usage: /<command> [# of levels]
permissions: 'worldedit.navigation.ascend' permissions: 'worldedit.navigation.ascend'
descend: descend:
description: Go down a floor description: Go down a floor
usage: /<command> usage: /<command> [# of floors]
permissions: 'worldedit.navigation.descend' permissions: 'worldedit.navigation.descend'
ceil: ceil:
description: Go to the celing description: Go to the celing
@ -143,6 +156,10 @@ commands:
description: Set a block on top of blocks in the region description: Set a block on top of blocks in the region
usage: /<command> <block> usage: /<command> <block>
permissions: 'worldedit.region.overlay' permissions: 'worldedit.region.overlay'
/naturalize:
description: 3 layers of dirt on top then rock below
usage: /<command>
permissions: 'worldedit.region.naturalize'
/walls: /walls:
description: Build the four sides of the selection description: Build the four sides of the selection
usage: /<command> <block> usage: /<command> <block>
@ -270,6 +287,10 @@ commands:
usage: /<command> [pattern] usage: /<command> [pattern]
aliases: ['material', 'fill'] aliases: ['material', 'fill']
permissions: 'worldedit.brush.options.material' permissions: 'worldedit.brush.options.material'
range:
description: Set the brush range
usage: /<command> [pattern]
permissions: 'worldedit.brush.options.range'
info: info:
description: Block information tool description: Block information tool
usage: /<command> usage: /<command>
@ -289,6 +310,11 @@ commands:
description: Block data cycler tool description: Block data cycler tool
usage: /<command> usage: /<command>
permissions: 'worldedit.tool.data-cycler' permissions: 'worldedit.tool.data-cycler'
floodfill:
description: Flood fill tool
usage: /<command>
aliases: ['flood']
permissions: 'worldedit.tool.flood-fill'
brush: brush:
description: Brush tool description: Brush tool
usage: /<command> usage: /<command>