diff --git a/src/EditSession.java b/src/EditSession.java index 99d5a71fe..5a9c46e2f 100755 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -17,10 +17,6 @@ * along with this program. If not, see . */ -import com.sk89q.worldedit.*; -import com.sk89q.worldedit.regions.*; -import com.sk89q.worldedit.blocks.*; -import com.sk89q.worldedit.patterns.*; import java.util.Map; import java.util.HashMap; import java.util.LinkedHashMap; @@ -31,6 +27,11 @@ import java.util.List; import java.util.ArrayList; import java.util.Collections; import java.util.Random; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.regions.*; +import com.sk89q.worldedit.bags.*; +import com.sk89q.worldedit.blocks.*; +import com.sk89q.worldedit.patterns.*; /** * This class can wrap all block editing operations into one "edit session" that @@ -43,6 +44,11 @@ import java.util.Random; * @author sk89q */ public class EditSession { + /** + * Random number generator. + */ + private static Random prng = new Random(); + /** * Stores the original blocks before modification. */ @@ -75,9 +81,13 @@ public class EditSession { */ private boolean queued = false; /** - * Random number generator. + * Block bag to use for getting blocks. */ - private static Random prng = new Random(); + private BlockBag blockBag; + /** + * List of missing blocks; + */ + private Set missingBlocks = new HashSet(); /** * Construct the object with a maximum number of blocks. @@ -89,6 +99,17 @@ public class EditSession { this.maxBlocks = maxBlocks; } + /** + * Construct the object with a maximum number of blocks and a block bag. + */ + public EditSession(int maxBlocks, BlockBag blockBag) { + if (maxBlocks < -1) { + throw new IllegalArgumentException("Max blocks must be >= -1"); + } + this.maxBlocks = maxBlocks; + this.blockBag = blockBag; + } + /** * Sets a block without changing history. * @@ -96,19 +117,41 @@ public class EditSession { * @param blockType * @return Whether the block changed */ - private static boolean rawSetBlock(Vector pt, BaseBlock block) { + private boolean rawSetBlock(Vector pt, BaseBlock block) { int y = pt.getBlockY(); if (y < 0 || y > 127) { return false; } // Clear the chest so that it doesn't drop items - if (ServerInterface.getBlockType(pt) == 54) { + if (ServerInterface.getBlockType(pt) == 54 && blockBag == null) { ServerInterface.clearChest(pt); } int id = block.getID(); + if (blockBag != null) { + int existing = ServerInterface.getBlockType(pt); + + if (id > 0) { + try { + blockBag.fetchPlacedBlock(id); + } catch (UnplaceableBlockException e) { + return false; + } catch (BlockBagException e) { + missingBlocks.add(id); + return false; + } + } + + if (existing > 0) { + try { + blockBag.storeDroppedBlock(existing); + } catch (BlockBagException e) { + } + } + } + boolean result = ServerInterface.setBlockType(pt, id); if (id != 0) { if (BlockType.usesData(id)) { @@ -121,7 +164,7 @@ public class EditSession { String[] text = signBlock.getText(); ServerInterface.setSignText(pt, text); // Chests - } else if (block instanceof ChestBlock) { + } else if (block instanceof ChestBlock && blockBag == null) { ChestBlock chestBlock = (ChestBlock)block; ServerInterface.setChestContents(pt, chestBlock.getItems()); // Mob spawners @@ -337,10 +380,14 @@ public class EditSession { BlockVector pt = (BlockVector)entry.getKey(); rawSetBlock(pt, (BaseBlock)entry.getValue()); } - - for (Map.Entry entry : queueLast) { - BlockVector pt = (BlockVector)entry.getKey(); - rawSetBlock(pt, (BaseBlock)entry.getValue()); + + // We don't want to place these blocks if other blocks were missing + // because it might cause the items to drop + if (blockBag == null || missingBlocks.size() == 0) { + for (Map.Entry entry : queueLast) { + BlockVector pt = (BlockVector)entry.getKey(); + rawSetBlock(pt, (BaseBlock)entry.getValue()); + } } queueAfter.clear(); @@ -1897,4 +1944,30 @@ public class EditSession { } return minY; } + + /** + * Gets the list of missing blocks and clears the list for the next + * operation. + * + * @return + */ + public Set popMissingBlocks() { + Set missingBlocks = this.missingBlocks; + this.missingBlocks = new HashSet(); + return missingBlocks; + } + + /** + * @return the blockBag + */ + public BlockBag getBlockBag() { + return blockBag; + } + + /** + * @param blockBag the blockBag to set + */ + public void setBlockBag(BlockBag blockBag) { + this.blockBag = blockBag; + } } diff --git a/src/PlayerInventoryBlockBag.java b/src/PlayerInventoryBlockBag.java new file mode 100644 index 000000000..35f480603 --- /dev/null +++ b/src/PlayerInventoryBlockBag.java @@ -0,0 +1,203 @@ +// $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 . +*/ + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.bags.*; + +public class PlayerInventoryBlockBag extends BlockBag { + /** + * Player instance. + */ + private Player player; + /** + * The player's inventory; + */ + private Item[] items; + + /** + * Construct the object. + * + * @param player + */ + public PlayerInventoryBlockBag(Player player) { + this.player = player; + } + + /** + * Loads inventory on first use. + */ + private void loadInventory() { + if (items == null) { + items = player.getInventory().getContents(); + } + } + + /** + * Get the player. + * + * @return + */ + public Player getPlayer() { + return player; + } + + /** + * Get a block. + * + * @param id + */ + public void fetchBlock(int id) throws BlockBagException { + if (id == 0) { + throw new IllegalArgumentException("Can't fetch air block"); + } + + loadInventory(); + + boolean found = false; + + for (int slot = 0; slot < items.length; slot++) { + Item item = items[slot]; + + if (item == null) continue; + + if (item.getItemId() == id) { + int amount = item.getAmount(); + + // Unlimited + if (amount < 0) { + return; + } + + if (amount > 1) { + item.setAmount(amount - 1); + found = true; + } else { + items[slot] = null; + found = true; + } + + break; + } + } + + if (found) { + } else { + throw new OutOfBlocksException(); + } + } + + /** + * Store a block. + * + * @param id + */ + public void storeBlock(int id) throws BlockBagException { + if (id == 0) { + throw new IllegalArgumentException("Can't store air block"); + } + + loadInventory(); + + boolean found = false; + int freeSlot = -1; + + for (int slot = 0; slot < items.length; slot++) { + Item item = items[slot]; + + // Delay using up a free slot until we know there are no stacks + // of this item to merge into + if (item == null) { + if (freeSlot == -1) { + freeSlot = slot; + } + continue; + } + + if (item.getItemId() == id) { + int amount = item.getAmount(); + + // Unlimited + if (amount < 0) { + return; + } + + if (amount < 64) { + item.setAmount(amount + 1); + found = true; + break; + } + } + } + + if (!found && freeSlot > -1) { + items[freeSlot] = new Item(id, 1); + found = true; + } + + if (found) { + } else { + throw new OutOfSpaceException(id); + } + } + + /** + * Flush any changes. This is called at the end. + */ + public void flushChanges() { + if (items != null) { + setContents(player.getInventory(), items); + items = null; + } + } + + /** + * Adds a position to be used a source. + * + * @param pos + * @return + */ + public void addSourcePosition(Vector pos) { + } + /** + * Adds a position to be used a source. + * + * @param pos + * @return + */ + public void addSingleSourcePosition(Vector pos) { + } + + /** + * Set the contents of an ItemArray. + * + * @param itemArray + * @param contents + */ + private static void setContents(Inventory itemArray, Item[] contents) { + int size = itemArray.getContentsSize(); + + for (int i = 0; i < size; i++) { + if (contents[i] == null) { + itemArray.removeItem(i); + } else { + itemArray.setSlot(contents[i], i); + } + } + } +} diff --git a/src/ServerInterface.java b/src/ServerInterface.java index cf0b817d4..3766a569b 100644 --- a/src/ServerInterface.java +++ b/src/ServerInterface.java @@ -18,12 +18,8 @@ */ import com.sk89q.worldedit.*; -import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.BlockType; import java.util.logging.Logger; -import java.util.Map; -import java.util.HashMap; import java.util.Random; /** @@ -336,6 +332,15 @@ public class ServerInterface { etc.getServer().dropItem(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ(), type, 1); } + + /** + * Get a block bag for a player. + * + * @param player + */ + public static PlayerInventoryBlockBag getPlayerBlockBag(WorldEditPlayer player) { + return new PlayerInventoryBlockBag(player.getPlayerObject()); + } /** * Simulate a block being mined. diff --git a/src/WorldEditListener.java b/src/WorldEditListener.java index cd3943559..aeb8e5e45 100755 --- a/src/WorldEditListener.java +++ b/src/WorldEditListener.java @@ -29,6 +29,7 @@ import java.util.logging.Handler; import java.util.logging.FileHandler; import java.io.*; import com.sk89q.worldedit.*; +import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.data.*; import com.sk89q.worldedit.filters.*; @@ -93,6 +94,8 @@ public class WorldEditListener extends PluginListener { private boolean superPickaxeDrop = true; private boolean superPickaxeManyDrop = true; private boolean noDoubleSlash = false; + private boolean useInventory = false; + private boolean useInventoryOverride = false; /** * Construct an instance of the plugin. @@ -190,6 +193,9 @@ public class WorldEditListener extends PluginListener { changeLimit = defaultChangeLimit; } session.setBlockChangeLimit(changeLimit); + session.setUseInventory(useInventory + && (!useInventoryOverride + || !player.getPlayerObject().canUseCommand("/worldeditunlimited"))); sessions.put(player, session); return session; } @@ -658,8 +664,10 @@ public class WorldEditListener extends PluginListener { // Undo } else if (split[0].equalsIgnoreCase("//undo")) { checkArgs(split, 0, 0, split[0]); - if (session.undo()) { + EditSession undone = session.undo(session.getBlockBag(player)); + if (undone != null) { player.print("Undo successful."); + flushBlockBag(player, undone); } else { player.printError("Nothing to undo."); } @@ -668,8 +676,10 @@ public class WorldEditListener extends PluginListener { // Redo } else if (split[0].equalsIgnoreCase("//redo")) { checkArgs(split, 0, 0, split[0]); - if (session.redo()) { + EditSession redone = session.redo(session.getBlockBag(player)); + if (redone != null) { player.print("Redo successful."); + flushBlockBag(player, redone); } else { player.printError("Nothing to redo."); } @@ -1967,7 +1977,7 @@ public class WorldEditListener extends PluginListener { // Legacy /, command if (split[0].equals("/,")) { split[0] = "//"; - } + } String searchCmd = split[0].toLowerCase(); @@ -1984,8 +1994,10 @@ public class WorldEditListener extends PluginListener { if (canUseCommand(ply, split[0])) { WorldEditPlayer player = new WorldEditPlayer(ply); WorldEditSession session = getSession(player); + BlockBag blockBag = session.getBlockBag(player); + EditSession editSession = - new EditSession(session.getBlockChangeLimit()); + new EditSession(session.getBlockChangeLimit(), blockBag); editSession.enableQueue(); long start = System.currentTimeMillis(); @@ -2000,6 +2012,8 @@ public class WorldEditListener extends PluginListener { long time = System.currentTimeMillis() - start; ply.sendMessage(Colors.Yellow + (time / 1000.0) + "s elapsed"); } + + flushBlockBag(player, editSession); } } } @@ -2036,6 +2050,48 @@ public class WorldEditListener extends PluginListener { return true; } + + /** + * Flush a block bag's changes to a player. + * + * @param player + * @param blockBag + * @param editSession + */ + private static void flushBlockBag(WorldEditPlayer player, + EditSession editSession) { + + BlockBag blockBag = editSession.getBlockBag(); + + if (blockBag != null) { + blockBag.flushChanges(); + } + + Set missingBlocks = editSession.popMissingBlocks(); + + if (missingBlocks.size() > 0) { + StringBuilder str = new StringBuilder(); + str.append("Missing these blocks: "); + int size = missingBlocks.size(); + int i = 0; + + for (Integer id : missingBlocks) { + BlockType type = BlockType.fromID(id); + + str.append(type != null + ? type.getName() + " (" + id + ")" + : id.toString()); + + i++; + + if (i != size) { + str.append(", "); + } + } + + player.printError(str.toString()); + } + } /** * Checks to see if the player can use a command or /worldedit. @@ -2095,6 +2151,8 @@ public class WorldEditListener extends PluginListener { superPickaxeDrop = properties.getBoolean("super-pickaxe-drop-items", true); superPickaxeManyDrop = properties.getBoolean("super-pickaxe-many-drop-items", false); noDoubleSlash = properties.getBoolean("no-double-slash", false); + useInventory = properties.getBoolean("use-inventory", false); + useInventoryOverride = properties.getBoolean("use-inventory-override", false); // Get allowed blocks allowedBlocks = new HashSet(); diff --git a/src/WorldEditSession.java b/src/WorldEditSession.java index 204b32a91..6b37658ba 100644 --- a/src/WorldEditSession.java +++ b/src/WorldEditSession.java @@ -18,6 +18,7 @@ */ import com.sk89q.worldedit.snapshots.Snapshot; +import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.*; @@ -58,6 +59,7 @@ public class WorldEditSession { private Tool tool = Tool.NONE; private int superPickaxeRange = 3; private int maxBlocksChanged = -1; + private boolean useInventory; private Snapshot snapshot; /** @@ -91,14 +93,16 @@ public class WorldEditSession { * * @return whether anything was undone */ - public boolean undo() { + public EditSession undo(BlockBag newBlockBag) { historyPointer--; if (historyPointer >= 0) { - history.get(historyPointer).undo(); - return true; + EditSession editSession = history.get(historyPointer); + editSession.setBlockBag(newBlockBag); + editSession.undo(); + return editSession; } else { historyPointer = 0; - return false; + return null; } } @@ -107,14 +111,16 @@ public class WorldEditSession { * * @return whether anything was redone */ - public boolean redo() { + public EditSession redo(BlockBag newBlockBag) { if (historyPointer < history.size()) { - history.get(historyPointer).redo(); + EditSession editSession = history.get(historyPointer); + editSession.setBlockBag(newBlockBag); + editSession.redo(); historyPointer++; - return true; + return editSession; } - return false; + return null; } /** @@ -336,6 +342,19 @@ public class WorldEditSession { placeAtPos1 = !placeAtPos1; return placeAtPos1; } + + /** + * Get a block bag for a player. + * + * @param player + * @return + */ + public BlockBag getBlockBag(WorldEditPlayer player) { + if (!useInventory) { + return null; + } + return ServerInterface.getPlayerBlockBag(player); + } /** * @return the snapshotName @@ -392,4 +411,18 @@ public class WorldEditSession { public void setTool(Tool tool) { this.tool = tool; } + + /** + * @return the useInventory + */ + public boolean isUsingInventory() { + return useInventory; + } + + /** + * @param useInventory the useInventory to set + */ + public void setUseInventory(boolean useInventory) { + this.useInventory = useInventory; + } } diff --git a/src/com/sk89q/worldedit/bags/BlockBag.java b/src/com/sk89q/worldedit/bags/BlockBag.java new file mode 100644 index 000000000..90bf92257 --- /dev/null +++ b/src/com/sk89q/worldedit/bags/BlockBag.java @@ -0,0 +1,153 @@ +// $Id$ +/* + * CraftBook + * 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.bags; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.*; + +/** + * Represents a source to get blocks from and store removed ones. + * + * @author sk89q + */ +public abstract class BlockBag { + /** + * Stores a block as if it was mined. + * + * @param id + * @throws BlockBagException + */ + public void storeDroppedBlock(int id) throws BlockBagException { + int dropped = BlockType.getDroppedBlock(id); + if (dropped > 0) { + storeBlock(dropped); + } + } + + /** + * Sets a block as if it was placed by hand. + * + * @param id + * @throws BlockBagException + */ + public void fetchPlacedBlock(int id) throws BlockBagException { + try { + // Blocks that can't be fetched... + if (id == BlockID.BEDROCK + || id == BlockID.GOLD_ORE + || id == BlockID.IRON_ORE + || id == BlockID.COAL_ORE + || id == BlockID.DIAMOND_ORE + || id == BlockID.LEAVES + || id == BlockID.TNT + || id == BlockID.MOB_SPAWNER + || id == BlockID.CROPS + || id == BlockID.REDSTONE_ORE + || id == BlockID.GLOWING_REDSTONE_ORE + || id == BlockID.SNOW + || id == BlockID.LIGHTSTONE + || id == BlockID.PORTAL) { + throw new UnplaceableBlockException(); + } + + // Override liquids + if (id == BlockID.WATER + || id == BlockID.STATIONARY_WATER + || id == BlockID.LAVA + || id == BlockID.STATIONARY_LAVA) { + return; + } + + fetchBlock(id); + } catch (OutOfBlocksException e) { + // Look for cobblestone + if (id == BlockID.STONE) { + fetchBlock(BlockID.COBBLESTONE); + // Look for dirt + } else if (id == BlockID.GRASS) { + fetchBlock(BlockID.DIRT); + // Look for redstone dust + } else if (id == BlockID.REDSTONE_WIRE) { + fetchBlock(331); + // Look for furnace + } else if (id == BlockID.BURNING_FURNACE) { + fetchBlock(BlockID.FURNACE); + // Look for lit redstone torch + } else if (id == BlockID.REDSTONE_TORCH_OFF) { + fetchBlock(BlockID.REDSTONE_TORCH_ON); + // Look for signs + } else if (id == BlockID.WALL_SIGN || id == BlockID.SIGN_POST) { + fetchBlock(323); + } else { + throw e; + } + } + } + + /** + * Get a block. + * + * @param id + */ + public abstract void fetchBlock(int id) throws BlockBagException; + + /** + * Store a block. + * + * @param id + */ + public abstract void storeBlock(int id) throws BlockBagException; + + /** + * Checks to see if a block exists without removing it. + * + * @param id + * @return whether the block exists + */ + public boolean peekBlock(int id) { + try { + fetchBlock(id); + storeBlock(id); + return true; + } catch (BlockBagException e) { + return false; + } + } + + /** + * Flush any changes. This is called at the end. + */ + public abstract void flushChanges(); + + /** + * Adds a position to be used a source. + * + * @param pos + * @return + */ + public abstract void addSourcePosition(Vector pos); + /** + * Adds a position to be used a source. + * + * @param pos + * @return + */ + public abstract void addSingleSourcePosition(Vector pos); +} diff --git a/src/com/sk89q/worldedit/bags/BlockBagException.java b/src/com/sk89q/worldedit/bags/BlockBagException.java new file mode 100644 index 000000000..2792c7b82 --- /dev/null +++ b/src/com/sk89q/worldedit/bags/BlockBagException.java @@ -0,0 +1,28 @@ +// $Id$ +/* + * CraftBook + * 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.bags; + +/** + * + * @author sk89q + */ +public class BlockBagException extends Exception { + private static final long serialVersionUID = 4672190086028430655L; +} diff --git a/src/com/sk89q/worldedit/bags/OutOfBlocksException.java b/src/com/sk89q/worldedit/bags/OutOfBlocksException.java new file mode 100644 index 000000000..34fe783e9 --- /dev/null +++ b/src/com/sk89q/worldedit/bags/OutOfBlocksException.java @@ -0,0 +1,28 @@ +// $Id$ +/* + * CraftBook + * 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.bags; + +/** + * + * @author sk89q + */ +public class OutOfBlocksException extends BlockBagException { + private static final long serialVersionUID = 7495899825677689509L; +} diff --git a/src/com/sk89q/worldedit/bags/OutOfSpaceException.java b/src/com/sk89q/worldedit/bags/OutOfSpaceException.java new file mode 100644 index 000000000..46ca23caa --- /dev/null +++ b/src/com/sk89q/worldedit/bags/OutOfSpaceException.java @@ -0,0 +1,48 @@ +// $Id$ +/* + * CraftBook + * 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.bags; + +/** + * + * @author sk89q + */ +public class OutOfSpaceException extends BlockBagException { + private static final long serialVersionUID = -2962840237632916821L; + + /** + * Stores the block ID. + */ + private int id; + + /** + * Construct the object. + * @param id + */ + public OutOfSpaceException(int id) { + this.id = id; + } + + /** + * @return the id + */ + public int getID() { + return id; + } +} diff --git a/src/com/sk89q/worldedit/bags/UnplaceableBlockException.java b/src/com/sk89q/worldedit/bags/UnplaceableBlockException.java new file mode 100644 index 000000000..0513e69fb --- /dev/null +++ b/src/com/sk89q/worldedit/bags/UnplaceableBlockException.java @@ -0,0 +1,30 @@ +// $Id$ +/* + * CraftBook + * 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.bags; + + +/** + * + * @author sk89q + */ +public class UnplaceableBlockException extends BlockBagException { + private static final long serialVersionUID = 7227883966999843526L; + +} diff --git a/src/com/sk89q/worldedit/blocks/BlockID.java b/src/com/sk89q/worldedit/blocks/BlockID.java new file mode 100644 index 000000000..d62d9cf29 --- /dev/null +++ b/src/com/sk89q/worldedit/blocks/BlockID.java @@ -0,0 +1,105 @@ +// $Id$ +/* + * CraftBook + * 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.blocks; + +/** + * List of block IDs. + * + * @author sk89q + */ +public final class BlockID { + public static final int AIR = 0; + public static final int STONE = 1; + public static final int GRASS = 2; + public static final int DIRT = 3; + public static final int COBBLESTONE = 4; + public static final int WOOD = 5; + public static final int SAPLING = 6; + public static final int BEDROCK = 7; + public static final int WATER = 8; + public static final int STATIONARY_WATER = 9; + public static final int LAVA = 10; + public static final int STATIONARY_LAVA = 11; + public static final int SAND = 12; + public static final int GRAVEL = 13; + public static final int GOLD_ORE = 14; + public static final int IRON_ORE = 15; + public static final int COAL_ORE = 16; + public static final int LOG = 17; + public static final int LEAVES = 18; + public static final int SPONGE = 19; + public static final int GLASS = 20; + public static final int CLOTH = 35; + public static final int YELLOW_FLOWER = 37; + public static final int RED_FLOWER = 38; + public static final int BROWN_MUSHROOM = 39; + public static final int RED_MUSHROOM = 40; + public static final int GOLD_BLOCK = 41; + public static final int IRON_BLOCK = 42; + public static final int DOUBLE_STEP = 43; + public static final int STEP = 44; + public static final int BRICK = 45; + public static final int TNT = 46; + public static final int BOOKCASE = 47; + public static final int MOSSY_COBBLESTONE = 48; + public static final int OBSIDIAN = 49; + public static final int TORCH = 50; + public static final int FIRE = 51; + public static final int MOB_SPAWNER = 52; + public static final int WOODEN_STAIRS = 53; + public static final int CHEST = 54; + public static final int REDSTONE_WIRE = 55; + public static final int DIAMOND_ORE = 56; + public static final int DIAMOND_BLOCK = 57; + public static final int WORKBENCH = 58; + public static final int CROPS = 59; + public static final int SOIL = 60; + public static final int FURNACE = 61; + public static final int BURNING_FURNACE = 62; + public static final int SIGN_POST = 63; + public static final int WOODEN_DOOR = 64; + public static final int LADDER = 65; + public static final int MINECART_TRACKS = 66; + public static final int COBBLESTONE_STAIRS = 67; + public static final int WALL_SIGN = 68; + public static final int LEVER = 69; + public static final int STONE_PRESSURE_PLATE = 70; + public static final int IRON_DOOR = 71; + public static final int WOODEN_PRESSURE_PLATE = 72; + public static final int REDSTONE_ORE = 73; + public static final int GLOWING_REDSTONE_ORE = 74; + public static final int REDSTONE_TORCH_OFF = 75; + public static final int REDSTONE_TORCH_ON = 76; + public static final int STONE_BUTTON = 77; + public static final int SNOW = 78; + public static final int ICE = 79; + public static final int SNOW_BLOCK = 80; + public static final int CACTUS = 81; + public static final int CLAY = 82; + public static final int REED = 83; + public static final int JUKEBOX = 84; + public static final int FENCE = 85; + public static final int PUMPKIN = 86; + public static final int NETHERSTONE = 87; + public static final int SLOW_SAND = 88; + public static final int LIGHTSTONE = 89; + public static final int PORTAL = 90; + public static final int JACKOLANTERN = 91; +} diff --git a/src/com/sk89q/worldedit/blocks/BlockType.java b/src/com/sk89q/worldedit/blocks/BlockType.java index 89de10e9c..88298e99c 100644 --- a/src/com/sk89q/worldedit/blocks/BlockType.java +++ b/src/com/sk89q/worldedit/blocks/BlockType.java @@ -108,6 +108,83 @@ public enum BlockType { PORTAL(90, "Portal", "portal"), LIGHTED_PUMPKIN(91, "Pumpkin (on)", new String[]{"pumpkinlighted", "pumpkinon", "litpumpkin"}); + /** + * Stores a list of dropped blocks for blocks. + */ + private static final Map blockDrops = new HashMap(); + + /** + * Static constructor. + */ + static { + blockDrops.put(1, 4); + blockDrops.put(2, 3); + blockDrops.put(3, 3); + blockDrops.put(4, 4); + blockDrops.put(5, 5); + blockDrops.put(6, 6); + blockDrops.put(7, -1); + blockDrops.put(12, 12); + blockDrops.put(13, 13); + blockDrops.put(14, 14); + blockDrops.put(15, 15); + blockDrops.put(16, 16); + blockDrops.put(17, 17); + blockDrops.put(18, 18); + blockDrops.put(19, 19); + blockDrops.put(20, 20); // Have to drop glass for //undo + blockDrops.put(35, 35); + blockDrops.put(37, 37); + blockDrops.put(38, 38); + blockDrops.put(39, 39); + blockDrops.put(40, 40); + blockDrops.put(41, 41); + blockDrops.put(42, 42); + blockDrops.put(43, 43); + blockDrops.put(44, 44); + blockDrops.put(45, 45); + blockDrops.put(47, 47); + blockDrops.put(48, 48); + blockDrops.put(49, 49); + blockDrops.put(50, 50); + blockDrops.put(53, 53); + blockDrops.put(54, 54); + blockDrops.put(55, 331); + blockDrops.put(56, 56); + blockDrops.put(57, 57); + blockDrops.put(58, 58); + blockDrops.put(59, 295); + blockDrops.put(60, 60); + blockDrops.put(61, 61); + blockDrops.put(62, 61); + blockDrops.put(63, 323); + blockDrops.put(64, 324); + blockDrops.put(65, 65); + blockDrops.put(66, 66); + blockDrops.put(67, 67); + blockDrops.put(68, 323); + blockDrops.put(69, 69); + blockDrops.put(70, 70); + blockDrops.put(71, 330); + blockDrops.put(72, 72); + blockDrops.put(73, 331); + blockDrops.put(74, 331); + blockDrops.put(75, 76); + blockDrops.put(76, 76); + blockDrops.put(77, 77); + blockDrops.put(80, 80); + blockDrops.put(81, 81); + blockDrops.put(82, 82); + blockDrops.put(83, 83); + blockDrops.put(84, 84); + blockDrops.put(85, 85); + blockDrops.put(86, 86); + blockDrops.put(87, 87); + blockDrops.put(88, 88); + blockDrops.put(89, 248); + blockDrops.put(91, 91); + } + /** * Stores a map of the IDs for fast access. */ @@ -301,4 +378,20 @@ public enum BlockType { || id == 77 // Stone button || id == 81; // Cactus } + + /** + * Get the block or item that would have been dropped. If nothing is + * dropped, 0 will be returned. If the block should not be destroyed + * (i.e. bedrock), -1 will be returned. + * + * @param id + * @return + */ + public static int getDroppedBlock(int id) { + Integer dropped = blockDrops.get(id); + if (dropped == null) { + return 0; + } + return dropped; + } } \ No newline at end of file