diff --git a/src/main/java/com/sk89q/jnbt/NBTConstants.java b/src/main/java/com/sk89q/jnbt/NBTConstants.java
index b7b3adb19..b66427551 100644
--- a/src/main/java/com/sk89q/jnbt/NBTConstants.java
+++ b/src/main/java/com/sk89q/jnbt/NBTConstants.java
@@ -62,5 +62,41 @@ public final class NBTConstants {
private NBTConstants() {
}
+
+ /**
+ * Convert a type ID to its corresponding {@link Tag} class.
+ *
+ * @param id type ID
+ * @return tag class
+ * @throws IllegalArgumentException thrown if the tag ID is not valid
+ */
+ public static Class extends Tag> getClassFromType(int id) {
+ switch (id) {
+ case TYPE_END:
+ return EndTag.class;
+ case TYPE_BYTE:
+ return ByteTag.class;
+ case TYPE_SHORT:
+ return ShortTag.class;
+ case TYPE_INT:
+ return IntTag.class;
+ case TYPE_LONG:
+ return LongTag.class;
+ case TYPE_FLOAT:
+ return FloatTag.class;
+ case TYPE_BYTE_ARRAY:
+ return ByteArrayTag.class;
+ case TYPE_STRING:
+ return StringTag.class;
+ case TYPE_LIST:
+ return ListTag.class;
+ case TYPE_COMPOUND:
+ return CompoundTag.class;
+ case TYPE_INT_ARRAY:
+ return IntArrayTag.class;
+ default:
+ throw new IllegalArgumentException("Unknown tag type ID of " + id);
+ }
+ }
}
diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java
index fef9bc23e..48c0181de 100644
--- a/src/main/java/com/sk89q/worldedit/EditSession.java
+++ b/src/main/java/com/sk89q/worldedit/EditSession.java
@@ -18,27 +18,35 @@
*/
package com.sk89q.worldedit;
-import java.util.Deque;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Stack;
-import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
import java.util.Random;
-import com.sk89q.worldedit.regions.*;
-import com.sk89q.worldedit.util.TreeGenerator;
-import com.sk89q.worldedit.bags.*;
-import com.sk89q.worldedit.blocks.*;
+import java.util.Set;
+import java.util.Stack;
+
+import com.sk89q.worldedit.bags.BlockBag;
+import com.sk89q.worldedit.bags.BlockBagException;
+import com.sk89q.worldedit.bags.UnplaceableBlockException;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.blocks.BlockID;
+import com.sk89q.worldedit.blocks.BlockType;
+import com.sk89q.worldedit.blocks.ContainerBlock;
+import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.expression.Expression;
import com.sk89q.worldedit.expression.ExpressionException;
import com.sk89q.worldedit.expression.runtime.RValue;
import com.sk89q.worldedit.masks.Mask;
-import com.sk89q.worldedit.patterns.*;
+import com.sk89q.worldedit.patterns.Pattern;
+import com.sk89q.worldedit.regions.CuboidRegion;
+import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.util.TreeGenerator;
/**
* This class can wrap all block editing operations into one "edit session" that
@@ -408,53 +416,7 @@ public class EditSession {
* @return BaseBlock
*/
public BaseBlock rawGetBlock(Vector pt) {
- world.checkLoadedChunk(pt);
-
- int type = world.getBlockType(pt);
- int data = world.getBlockData(pt);
-
- switch (type) {
- case BlockID.WALL_SIGN:
- case BlockID.SIGN_POST: {
- SignBlock block = new SignBlock(type, data);
- world.copyFromWorld(pt, block);
- return block;
- }
-
- case BlockID.CHEST: {
- ChestBlock block = new ChestBlock(data);
- world.copyFromWorld(pt, block);
- return block;
- }
-
- case BlockID.FURNACE:
- case BlockID.BURNING_FURNACE: {
- FurnaceBlock block = new FurnaceBlock(type, data);
- world.copyFromWorld(pt, block);
- return block;
- }
-
- case BlockID.DISPENSER: {
- DispenserBlock block = new DispenserBlock(data);
- world.copyFromWorld(pt, block);
- return block;
- }
-
- case BlockID.MOB_SPAWNER: {
- MobSpawnerBlock block = new MobSpawnerBlock(data);
- world.copyFromWorld(pt, block);
- return block;
- }
-
- case BlockID.NOTE_BLOCK: {
- NoteBlock block = new NoteBlock(data);
- world.copyFromWorld(pt, block);
- return block;
- }
-
- default:
- return new BaseBlock(type, data);
- }
+ return world.getBlock(pt);
}
/**
@@ -464,8 +426,8 @@ public class EditSession {
*/
public void undo(EditSession sess) {
for (Map.Entry entry : original) {
- BlockVector pt = (BlockVector) entry.getKey();
- sess.smartSetBlock(pt, (BaseBlock) entry.getValue());
+ BlockVector pt = entry.getKey();
+ sess.smartSetBlock(pt, entry.getValue());
}
sess.flushQueue();
}
@@ -477,8 +439,8 @@ public class EditSession {
*/
public void redo(EditSession sess) {
for (Map.Entry entry : current) {
- BlockVector pt = (BlockVector) entry.getKey();
- sess.smartSetBlock(pt, (BaseBlock) entry.getValue());
+ BlockVector pt = entry.getKey();
+ sess.smartSetBlock(pt, entry.getValue());
}
sess.flushQueue();
}
@@ -727,8 +689,8 @@ public class EditSession {
final Set dirtyChunks = new HashSet();
for (Map.Entry entry : queueAfter) {
- BlockVector pt = (BlockVector) entry.getKey();
- rawSetBlock(pt, (BaseBlock) entry.getValue());
+ BlockVector pt = entry.getKey();
+ rawSetBlock(pt, entry.getValue());
// TODO: use ChunkStore.toChunk(pt) after optimizing it.
if (fastMode) {
@@ -740,8 +702,8 @@ public class EditSession {
// 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());
+ BlockVector pt = entry.getKey();
+ rawSetBlock(pt, entry.getValue());
// TODO: use ChunkStore.toChunk(pt) after optimizing it.
if (fastMode) {
diff --git a/src/main/java/com/sk89q/worldedit/LocalWorld.java b/src/main/java/com/sk89q/worldedit/LocalWorld.java
index 11d1565f3..865ab2636 100644
--- a/src/main/java/com/sk89q/worldedit/LocalWorld.java
+++ b/src/main/java/com/sk89q/worldedit/LocalWorld.java
@@ -21,9 +21,19 @@ package com.sk89q.worldedit;
import java.util.PriorityQueue;
import java.util.Random;
+
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack;
+import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
+import com.sk89q.worldedit.blocks.ChestBlock;
+import com.sk89q.worldedit.blocks.DispenserBlock;
+import com.sk89q.worldedit.blocks.FurnaceBlock;
+import com.sk89q.worldedit.blocks.MobSpawnerBlock;
+import com.sk89q.worldedit.blocks.NoteBlock;
+import com.sk89q.worldedit.blocks.SignBlock;
+import com.sk89q.worldedit.foundation.Block;
+import com.sk89q.worldedit.foundation.World;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator;
@@ -32,7 +42,7 @@ import com.sk89q.worldedit.util.TreeGenerator;
*
* @author sk89q
*/
-public abstract class LocalWorld {
+public abstract class LocalWorld implements World {
/**
* Named flags to use as parameters to {@link LocalWorld#killMobs(Vector, double, int)}
*/
@@ -64,6 +74,7 @@ public abstract class LocalWorld {
* @param type
* @return
*/
+ @Deprecated
public abstract boolean setBlockType(Vector pt, int type);
/**
@@ -73,6 +84,7 @@ public abstract class LocalWorld {
* @param type
* @return
*/
+ @Deprecated
public boolean setBlockTypeFast(Vector pt, int type) {
return setBlockType(pt, type);
}
@@ -83,6 +95,7 @@ public abstract class LocalWorld {
* @param pt
* @return
*/
+ @Deprecated
public abstract int getBlockType(Vector pt);
/**
@@ -91,7 +104,7 @@ public abstract class LocalWorld {
* @param pt
* @param data
*/
-
+ @Deprecated
public abstract void setBlockData(Vector pt, int data);
/**
@@ -100,6 +113,7 @@ public abstract class LocalWorld {
* @param pt
* @param data
*/
+ @Deprecated
public abstract void setBlockDataFast(Vector pt, int data);
/**
@@ -124,6 +138,7 @@ public abstract class LocalWorld {
* @param data
* @return
*/
+ @Deprecated
public boolean setTypeIdAndData(Vector pt, int type, int data) {
boolean ret = setBlockType(pt, type);
setBlockData(pt, data);
@@ -137,6 +152,7 @@ public abstract class LocalWorld {
* @param data
* @return
*/
+ @Deprecated
public boolean setTypeIdAndDataFast(Vector pt, int type, int data) {
boolean ret = setBlockTypeFast(pt, type);
setBlockDataFast(pt, data);
@@ -149,6 +165,7 @@ public abstract class LocalWorld {
* @param pt
* @return
*/
+ @Deprecated
public abstract int getBlockData(Vector pt);
/**
@@ -482,6 +499,7 @@ public abstract class LocalWorld {
public boolean queueBlockBreakEffect(ServerInterface server, Vector position, int blockId, double priority) {
if (taskId == -1) {
taskId = server.schedule(0, 1, new Runnable() {
+ @Override
public void run() {
int max = Math.max(1, Math.min(30, effectQueue.size() / 3));
for (int i = 0; i < max; ++i) {
@@ -509,4 +527,73 @@ public abstract class LocalWorld {
public int killEntities(LocalEntity... entities) {
return 0;
}
+
+ @Override
+ public boolean setBlock(Vector pt, Block block, boolean notifyAdjacent) {
+ boolean successful;
+
+ // Default implementation will call the old deprecated methods
+ if (notifyAdjacent) {
+ successful = setTypeIdAndData(pt, block.getId(), block.getData());
+ } else {
+ successful = setTypeIdAndDataFast(pt, block.getId(), block.getData());
+ }
+
+ if (block instanceof BaseBlock) {
+ copyToWorld(pt, (BaseBlock) block);
+ }
+
+ return successful;
+ }
+
+ @Override
+ public BaseBlock getBlock(Vector pt) {
+ checkLoadedChunk(pt);
+
+ int type = getBlockType(pt);
+ int data = getBlockData(pt);
+
+ switch (type) {
+ case BlockID.WALL_SIGN:
+ case BlockID.SIGN_POST: {
+ SignBlock block = new SignBlock(type, data);
+ copyFromWorld(pt, block);
+ return block;
+ }
+
+ case BlockID.CHEST: {
+ ChestBlock block = new ChestBlock(data);
+ copyFromWorld(pt, block);
+ return block;
+ }
+
+ case BlockID.FURNACE:
+ case BlockID.BURNING_FURNACE: {
+ FurnaceBlock block = new FurnaceBlock(type, data);
+ copyFromWorld(pt, block);
+ return block;
+ }
+
+ case BlockID.DISPENSER: {
+ DispenserBlock block = new DispenserBlock(data);
+ copyFromWorld(pt, block);
+ return block;
+ }
+
+ case BlockID.MOB_SPAWNER: {
+ MobSpawnerBlock block = new MobSpawnerBlock(data);
+ copyFromWorld(pt, block);
+ return block;
+ }
+
+ case BlockID.NOTE_BLOCK: {
+ NoteBlock block = new NoteBlock(data);
+ copyFromWorld(pt, block);
+ return block;
+ }
+
+ default:
+ return new BaseBlock(type, data);
+ }
+ }
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java b/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java
index 1ed559b60..121048550 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java
@@ -20,26 +20,20 @@
package com.sk89q.worldedit.blocks;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
+import com.sk89q.worldedit.foundation.Block;
/**
* Represents a block.
*
+ * @see Block new class to replace this one
* @author sk89q
*/
-public class BaseBlock {
+public class BaseBlock extends Block {
+
/**
- * BaseBlock type.
- */
- private short type = 0;
- /**
- * BaseBlock data.
- */
- private short data = 0;
-
- /**
- * Construct the block with its type.
+ * Construct the block with its type, with default data value 0.
*
- * @param type
+ * @param type type ID of block
*/
public BaseBlock(int type) {
this(type, 0);
@@ -48,40 +42,29 @@ public class BaseBlock {
/**
* Construct the block with its type and data.
*
- * @param type
- * @param data
+ * @param type type ID of block
+ * @param data data value
*/
public BaseBlock(int type, int data) {
- this.type = (short) type;
- this.data = (short) data;
+ super(type, data);
}
/**
+ * Get the type of block.
+ *
* @return the type
*/
public int getType() {
- return (int) type;
+ return getId();
}
/**
+ * Set the type of block.
+ *
* @param type the type to set
*/
public void setType(int type) {
- this.type = (short) type;
- }
-
- /**
- * @return the data
- */
- public int getData() {
- return (int) data;
- }
-
- /**
- * @param data the data to set
- */
- public void setData(int data) {
- this.data = (short) data;
+ setId(type);
}
/**
@@ -90,24 +73,28 @@ public class BaseBlock {
* @return if air
*/
public boolean isAir() {
- return type == BlockID.AIR;
+ return getType() == BlockID.AIR;
}
/**
* Rotate this block 90 degrees.
+ *
+ * @return new data value
*/
public int rotate90() {
- int newData = BlockData.rotate90(type, data);
- this.data = (short) newData;
- return data;
+ int newData = BlockData.rotate90(getType(), getData());
+ setData(newData);
+ return newData;
}
/**
* Rotate this block -90 degrees.
+ *
+ * @return new data value
*/
public int rotate90Reverse() {
- int newData = BlockData.rotate90Reverse(type, data);
- this.data = (short) newData;
+ int newData = BlockData.rotate90Reverse(getType(), getData());
+ setData((short) newData);
return newData;
}
@@ -118,56 +105,55 @@ public class BaseBlock {
* @return new data value
*/
public int cycleData(int increment) {
- int newData = BlockData.cycle(this.type, this.data, increment);
- this.data = (short) newData;
+ int newData = BlockData.cycle(getType(), getData(), increment);
+ setData((short) newData);
return newData;
}
/**
* Flip this block.
+ *
+ * @return this block
*/
public BaseBlock flip() {
- data = (short) BlockData.flip(type, data);
+ setData((short) BlockData.flip(getType(), getData()));
return this;
}
/**
* Flip this block.
- * @param direction
+ *
+ * @param direction direction to flip in
+ * @return this block
*/
public BaseBlock flip(FlipDirection direction) {
- data = (short) BlockData.flip(type, data, direction);
+ setData((short) BlockData.flip(getType(), getData(), direction));
return this;
}
+ /**
+ * Checks whether the type ID and data value are equal.
+ */
@Override
public boolean equals(Object o) {
if (!(o instanceof BaseBlock)) {
return false;
}
- return type == ((BaseBlock) o).type && data == ((BaseBlock) o).data;
- }
-
- public boolean equalsFuzzy(BaseBlock o) {
- return (type == o.type && data == o.data) || data == -1 || o.data == -1;
- }
-
- @Override
- public int hashCode() {
- int ret = type << 3;
- if (data != (byte) -1) ret |= data;
- return ret;
- }
-
- @Override
- public String toString() {
- return "BaseBlock id: " + getType() + " with damage: " + getData();
+ return getType() == ((BaseBlock) o).getType() && getData() == ((BaseBlock) o).getData();
+ }
+
+ /**
+ * Checks if the type is the same, and if data is the same if only data != -1.
+ *
+ * @param o other block
+ * @return true if equal
+ */
+ public boolean equalsFuzzy(BaseBlock o) {
+ return (getType() == o.getType() && getData() == o.getData()) || getData() == -1 || o.getData() == -1;
}
/**
- *
- *
* @param iter
* @return
* @deprecated This method is silly
diff --git a/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java b/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java
index 5494ee991..3d06ae3ff 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/BaseItem.java
@@ -23,44 +23,41 @@ import java.util.HashMap;
import java.util.Map;
/**
- * Represents an item.
+ * Represents an item, without an amount value. See {@link BaseItemStack} for an instance
+ * with stack amount information.
*
* @author sk89q
*/
public class BaseItem {
- /**
- * Item ID.
- */
+
private int id;
- /**
- * Item damage.
- */
- private short damage;
-
- private Map enchantments = new HashMap();
+ private short data;
+ private final Map enchantments = new HashMap();
/**
* Construct the object.
*
- * @param id
+ * @param id ID of the item
*/
public BaseItem(int id) {
this.id = id;
- this.damage = 0;
+ this.data = 0;
}
/**
* Construct the object.
*
- * @param id
- * @param damage
+ * @param id ID of the item
+ * @param data data value of the item
*/
- public BaseItem(int id, short damage) {
+ public BaseItem(int id, short data) {
this.id = id;
- this.damage = damage;
+ this.data = data;
}
/**
+ * Get the type of item.
+ *
* @return the id
*/
public int getType() {
@@ -68,6 +65,8 @@ public class BaseItem {
}
/**
+ * Get the type of item.
+ *
* @param id the id to set
*/
public void setType(int id) {
@@ -75,19 +74,48 @@ public class BaseItem {
}
/**
+ * Get the damage value.
+ *
* @return the damage
*/
+ @Deprecated
public short getDamage() {
- return damage;
+ return data;
}
/**
- * @param damage the damage to set
+ * Get the data value.
+ *
+ * @return the data
*/
- public void setDamage(short damage) {
- this.damage = damage;
+ public short getData() {
+ return data;
}
+ /**
+ * Set the data value.
+ *
+ * @param data the damage to set
+ */
+ @Deprecated
+ public void setDamage(short data) {
+ this.data = data;
+ }
+
+ /**
+ * Set the data value.
+ *
+ * @param data the damage to set
+ */
+ public void setData(short data) {
+ this.data = data;
+ }
+
+ /**
+ * Get the map of enchantments.
+ *
+ * @return map of enchantments
+ */
public Map getEnchantments() {
return enchantments;
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java b/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java
index 5d12a9bc9..d23c268b9 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/BaseItemStack.java
@@ -31,9 +31,9 @@ public class BaseItemStack extends BaseItem {
private int amount = 1;
/**
- * Construct the object.
+ * Construct the object with default stack size of one, with data value of 0.
*
- * @param id
+ * @param id with data value of 0.
*/
public BaseItemStack(int id) {
super(id);
@@ -42,8 +42,8 @@ public class BaseItemStack extends BaseItem {
/**
* Construct the object.
*
- * @param id
- * @param amount
+ * @param id type ID
+ * @param amount amount in the stack
*/
public BaseItemStack(int id, int amount) {
super(id);
@@ -53,16 +53,18 @@ public class BaseItemStack extends BaseItem {
/**
* Construct the object.
*
- * @param id
- * @param amount
- * @param damage
+ * @param id type ID
+ * @param amount amount in the stack
+ * @param data data value
*/
- public BaseItemStack(int id, int amount, short damage) {
- super(id, damage);
+ public BaseItemStack(int id, int amount, short data) {
+ super(id, data);
this.amount = amount;
}
/**
+ * Get the number of items in the stack.
+ *
* @return the amount
*/
public int getAmount() {
@@ -70,6 +72,8 @@ public class BaseItemStack extends BaseItem {
}
/**
+ * Set the amount of items in the stack.
+ *
* @param amount the amount to set
*/
public void setAmount(int amount) {
diff --git a/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java b/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java
index e21bd822a..1b66e4304 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java
@@ -19,80 +19,71 @@
package com.sk89q.worldedit.blocks;
-import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.data.*;
-import java.util.Map;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import java.util.ArrayList;
+import java.util.Map;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.data.DataException;
/**
- * Represents chests.
+ * Represents a chest block.
*
* @author sk89q
*/
public class ChestBlock extends ContainerBlock {
/**
- * Construct the chest block.
+ * Construct an empty chest block with the default orientation (data value).
*/
public ChestBlock() {
super(BlockID.CHEST, 27);
}
/**
- * Construct the chest block.
+ * Construct an empty chest block with a custom data value.
*
- * @param data
+ * @param data data indicating the position of the chest
*/
public ChestBlock(int data) {
super(BlockID.CHEST, data, 27);
}
/**
- * Construct the chest block.
+ * Construct the chest block with a custom data value and a list of items.
*
- * @param data
- * @param items
+ * @param data data indicating the position of the chest
+ * @param items array of items
*/
public ChestBlock(int data, BaseItemStack[] items) {
super(BlockID.CHEST, data, 27);
setItems(items);
}
- /**
- * Get the tile entity ID.
- *
- * @return
- */
- public String getTileEntityID() {
+ @Override
+ public String getNbtId() {
return "Chest";
}
- /**
- * Store additional tile entity data. Returns true if the data is used.
- *
- * @return map of values
- * @throws DataException
- */
- public Map toTileEntityNBT()
- throws DataException {
+ @Override
+ public CompoundTag getNbtData() {
Map values = new HashMap();
values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(getItems())));
- return values;
+ return new CompoundTag(getNbtId(), values);
}
- /**
- * Get additional information from the title entity data.
- *
- * @param values
- * @throws DataException
- */
- public void fromTileEntityNBT(Map values)
- throws DataException {
- if (values == null) {
+ @Override
+ public void setNbtData(CompoundTag rootTag) throws DataException {
+ if (rootTag == null) {
return;
}
+
+ Map values = rootTag.getValue();
Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Chest")) {
@@ -100,6 +91,7 @@ public class ChestBlock extends ContainerBlock {
}
List items = new ArrayList();
+
for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) {
if (!(tag instanceof CompoundTag)) {
throw new DataException("CompoundTag expected as child tag of Chest's Items");
diff --git a/src/main/java/com/sk89q/worldedit/blocks/ContainerBlock.java b/src/main/java/com/sk89q/worldedit/blocks/ContainerBlock.java
index 394ff27b0..614dc4f59 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/ContainerBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/ContainerBlock.java
@@ -19,6 +19,11 @@
package com.sk89q.worldedit.blocks;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
@@ -27,17 +32,13 @@ import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.data.DataException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
/**
* Represents a block that stores items.
*
* @author sk89q
*/
public abstract class ContainerBlock extends BaseBlock implements TileEntityBlock {
+
private BaseItemStack[] items;
public ContainerBlock(int type, int inventorySize) {
@@ -50,7 +51,6 @@ public abstract class ContainerBlock extends BaseBlock implements TileEntityBloc
this.items = new BaseItemStack[inventorySize];
}
-
/**
* Get the list of items.
*
@@ -68,6 +68,11 @@ public abstract class ContainerBlock extends BaseBlock implements TileEntityBloc
public void setItems(BaseItemStack[] items) {
this.items = items;
}
+
+ @Override
+ public boolean hasNbtData() {
+ return true;
+ }
public Map serializeItem(BaseItemStack item) {
Map data = new HashMap();
diff --git a/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java b/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java
index 0e5367c89..81c8e9c9b 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java
@@ -19,12 +19,17 @@
package com.sk89q.worldedit.blocks;
-import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.data.*;
-import java.util.Map;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import java.util.ArrayList;
+import java.util.Map;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.data.DataException;
/**
* Represents dispensers.
@@ -34,65 +39,52 @@ import java.util.ArrayList;
public class DispenserBlock extends ContainerBlock {
/**
- * Construct the dispenser block.
+ * Construct an empty dispenser block.
*/
public DispenserBlock() {
super(BlockID.DISPENSER, 9);
}
/**
- * Construct the dispenser block.
+ * Construct an empty dispenser block.
*
- * @param data
+ * @param data data value (orientation)
*/
public DispenserBlock(int data) {
super(BlockID.DISPENSER, data, 9);
}
/**
- * Construct the dispenser block.
+ * Construct a dispenser block with the given orientation and inventory.
*
- * @param data
- * @param items
+ * @param data data value (orientation)
+ * @param items array of items in the inventory
*/
public DispenserBlock(int data, BaseItemStack[] items) {
super(BlockID.DISPENSER, data, 9);
this.setItems(items);
}
- /**
- * Get the tile entity ID.
- *
- * @return
- */
- public String getTileEntityID() {
+ @Override
+ public String getNbtId() {
return "Trap";
}
- /**
- * Store additional tile entity data. Returns true if the data is used.
- *
- * @return map of values
- * @throws DataException
- */
- public Map toTileEntityNBT()
- throws DataException {
+ @Override
+ public CompoundTag getNbtData() {
Map values = new HashMap();
- values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(getItems())));
- return values;
+ values.put("Items", new ListTag("Items", CompoundTag.class,
+ serializeInventory(getItems())));
+ return new CompoundTag(getNbtId(), values);
}
- /**
- * Get additional information from the title entity data.
- *
- * @param values
- * @throws DataException
- */
- public void fromTileEntityNBT(Map values)
- throws DataException {
- if (values == null) {
+ @Override
+ public void setNbtData(CompoundTag rootTag) throws DataException {
+ if (rootTag == null) {
return;
}
+
+ Map values = rootTag.getValue();
Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Trap")) {
diff --git a/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java b/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java
index a65c875cb..b0187a262 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java
@@ -15,60 +15,58 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*/
+ */
package com.sk89q.worldedit.blocks;
-import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.data.*;
-
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.HashMap;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.ShortTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.data.DataException;
/**
- * Represents furnaces.
- *
+ * Represents a furnace block.
+ *
* @author sk89q
*/
public class FurnaceBlock extends ContainerBlock {
- /**
- * Fuel time.
- */
private short burnTime;
-
- /**
- * Cook time.
- */
private short cookTime;
/**
- * Construct the chest block.
- *
- * @param type
+ * Construct an empty furnace block with the default orientation.
+ *
+ * @param type type ID
*/
public FurnaceBlock(int type) {
super(type, 2);
}
/**
- * Construct the chest block.
- *
- * @param type
- * @param data
+ * Construct an empty furnace block with a given orientation.
+ *
+ * @param type type ID
+ * @param data orientation
*/
public FurnaceBlock(int type, int data) {
super(type, data, 2);
}
/**
- * Construct the chest block.
- *
- * @param type
- * @param data
- * @param items
+ * Construct an furnace block with a given orientation and inventory.
+ *
+ * @param type type ID
+ * @param data orientation
+ * @param items inventory items
*/
public FurnaceBlock(int type, int data, BaseItemStack[] items) {
super(type, data, 2);
@@ -76,71 +74,67 @@ public class FurnaceBlock extends ContainerBlock {
}
/**
- * @return the burnTime
+ * Get the burn time.
+ *
+ * @return the burn time
*/
public short getBurnTime() {
return burnTime;
}
/**
- * @param burnTime the burnTime to set
+ * Set the burn time.
+ *
+ * @param burnTime the burn time
*/
public void setBurnTime(short burnTime) {
this.burnTime = burnTime;
}
/**
- * @return the cookTime
+ * Get the cook time.
+ *
+ * @return the cook time
*/
public short getCookTime() {
return cookTime;
}
/**
- * @param cookTime the cookTime to set
+ * Set the cook time.
+ *
+ * @param cookTime the cook time to set
*/
public void setCookTime(short cookTime) {
this.cookTime = cookTime;
}
- /**
- * Get the tile entity ID.
- *
- * @return
- */
- public String getTileEntityID() {
+ @Override
+ public String getNbtId() {
return "Furnace";
}
- /**
- * Store additional tile entity data. Returns true if the data is used.
- *
- * @return map of values
- * @throws DataException
- */
- public Map toTileEntityNBT()
- throws DataException {
+ @Override
+ public CompoundTag getNbtData() {
Map values = new HashMap();
- values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(getItems())));
+ values.put("Items", new ListTag("Items", CompoundTag.class,
+ serializeInventory(getItems())));
values.put("BurnTime", new ShortTag("BurnTime", burnTime));
values.put("CookTime", new ShortTag("CookTime", cookTime));
- return values;
+ return new CompoundTag(getNbtId(), values);
}
- /**
- * Get additional information from the title entity data.
- *
- * @param values
- * @throws DataException
- */
- public void fromTileEntityNBT(Map values)
- throws DataException {
- if (values == null) {
+ @Override
+ public void setNbtData(CompoundTag rootTag) throws DataException {
+ if (rootTag == null) {
return;
}
+
+ Map values = rootTag.getValue();
Tag t = values.get("id");
- if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Furnace")) {
+ if (!(t instanceof StringTag)
+ || !((StringTag) t).getValue().equals("Furnace")) {
throw new DataException("'Furnace' tile entity expected");
}
@@ -150,7 +144,8 @@ public class FurnaceBlock extends ContainerBlock {
for (Tag tag : items.getValue()) {
if (!(tag instanceof CompoundTag)) {
- throw new DataException("CompoundTag expected as child tag of Furnace Items");
+ throw new DataException(
+ "CompoundTag expected as child tag of Furnace Items");
}
compound.add((CompoundTag) tag);
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
index 92b08315e..14896d050 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
@@ -19,30 +19,29 @@
package com.sk89q.worldedit.blocks;
-import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.MobType;
-import com.sk89q.worldedit.data.*;
-import java.util.Map;
import java.util.HashMap;
+import java.util.Map;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.ShortTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.MobType;
+import com.sk89q.worldedit.data.DataException;
/**
- * Represents mob spawners.
+ * A mob spawner block.
*
* @author sk89q
*/
public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
- /**
- * Store mob spawn type.
- */
+
private String mobType;
- /**
- * Delay until next spawn.
- */
private short delay;
/**
- * Construct the mob spawner block.
- *
+ * Construct the mob spawner block with a pig as the mob type.
*/
public MobSpawnerBlock() {
super(BlockID.MOB_SPAWNER);
@@ -50,9 +49,9 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
}
/**
- * Construct the mob spawner block.
+ * Construct the mob spawner block with a given mob type.
*
- * @param mobType
+ * @param mobType mob type
*/
public MobSpawnerBlock(String mobType) {
super(BlockID.MOB_SPAWNER);
@@ -60,9 +59,9 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
}
/**
- * Construct the mob spawner block.
+ * Construct the mob spawner block with a specified data value.
*
- * @param data
+ * @param data data value
*/
public MobSpawnerBlock(int data) {
super(BlockID.MOB_SPAWNER, data);
@@ -71,8 +70,8 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
/**
* Construct the mob spawner block.
*
- * @param data
- * @param mobType
+ * @param data data value
+ * @param mobType mob type
*/
public MobSpawnerBlock(int data, String mobType) {
super(BlockID.MOB_SPAWNER, data);
@@ -82,7 +81,7 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
/**
* Get the mob type.
*
- * @return
+ * @return the mob type
*/
public String getMobType() {
return mobType;
@@ -91,13 +90,15 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
/**
* Set the mob type.
*
- * @param mobType
+ * @param mobType the mob type
*/
public void setMobType(String mobType) {
this.mobType = mobType;
}
/**
+ * Get the spawn delay.
+ *
* @return the delay
*/
public short getDelay() {
@@ -105,47 +106,40 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
}
/**
+ * Set the spawn delay.
+ *
* @param delay the delay to set
*/
public void setDelay(short delay) {
this.delay = delay;
}
+
+ @Override
+ public boolean hasNbtData() {
+ return true;
+ }
- /**
- * Get the tile entity ID.
- *
- * @return
- */
- public String getTileEntityID() {
+ @Override
+ public String getNbtId() {
return "MobSpawner";
}
- /**
- * Store additional tile entity data. Returns true if the data is used.
- *
- * @return map of values
- * @throws DataException
- */
- public Map toTileEntityNBT()
- throws DataException {
+ @Override
+ public CompoundTag getNbtData() {
Map values = new HashMap();
values.put("EntityId", new StringTag("EntityId", mobType));
values.put("Delay", new ShortTag("Delay", delay));
- return values;
+ return new CompoundTag(getNbtId(), values);
}
- /**
- * Get additional information from the title entity data.
- *
- * @param values
- * @throws DataException
- */
- public void fromTileEntityNBT(Map values)
- throws DataException {
- if (values == null) {
+ @Override
+ public void setNbtData(CompoundTag rootTag) throws DataException {
+ if (rootTag == null) {
return;
}
+ Map values = rootTag.getValue();
+
Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("MobSpawner")) {
throw new DataException("'MobSpawner' tile entity expected");
diff --git a/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java b/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java
index 5a382ed2d..283ca4c37 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/NoteBlock.java
@@ -15,27 +15,30 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*/
+ */
package com.sk89q.worldedit.blocks;
-import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.data.*;
-import java.util.Map;
import java.util.HashMap;
+import java.util.Map;
+
+import com.sk89q.jnbt.ByteTag;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.data.DataException;
/**
- *
+ * A note block.
+ *
* @author sk89q
*/
public class NoteBlock extends BaseBlock implements TileEntityBlock {
- /**
- * Stores the pitch.
- */
+
private byte note;
/**
- * Construct the note block.
+ * Construct the note block with a data value of 0.
*/
public NoteBlock() {
super(BlockID.NOTE_BLOCK);
@@ -43,9 +46,9 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
}
/**
- * Construct the note block.
- *
- * @param data
+ * Construct the note block with a given data value.
+ *
+ * @param data data value
*/
public NoteBlock(int data) {
super(BlockID.NOTE_BLOCK, data);
@@ -53,10 +56,10 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
}
/**
- * Construct the note block.
- *
- * @param data
- * @param note
+ * Construct the note block with a given data value and note.
+ *
+ * @param data data value
+ * @param note note
*/
public NoteBlock(int data, byte note) {
super(BlockID.NOTE_BLOCK, data);
@@ -64,6 +67,8 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
}
/**
+ * Get the note.
+ *
* @return the note
*/
public byte getNote() {
@@ -71,50 +76,44 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
}
/**
+ * Set the note.
+ *
* @param note the note to set
*/
public void setNote(byte note) {
this.note = note;
}
+
+ @Override
+ public boolean hasNbtData() {
+ return true;
+ }
- /**
- * Return the name of the title entity ID.
- *
- * @return title entity ID
- */
- public String getTileEntityID() {
+ @Override
+ public String getNbtId() {
return "Music";
}
- /**
- * Store additional tile entity data. Returns true if the data is used.
- *
- * @return map of values
- * @throws DataException
- */
- public Map toTileEntityNBT()
- throws DataException {
+ @Override
+ public CompoundTag getNbtData() {
Map values = new HashMap();
values.put("note", new ByteTag("note", note));
- return values;
+ return new CompoundTag(getNbtId(), values);
}
- /**
- * Get additional information from the title entity data.
- *
- * @param values
- * @throws DataException
- */
- public void fromTileEntityNBT(Map values)
- throws DataException {
- if (values == null) {
+ @Override
+ public void setNbtData(CompoundTag rootTag) throws DataException {
+ if (rootTag == null) {
return;
}
+ Map values = rootTag.getValue();
+
Tag t;
t = values.get("id");
- if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Music")) {
+ if (!(t instanceof StringTag)
+ || !((StringTag) t).getValue().equals("Music")) {
throw new DataException("'Music' tile entity expected");
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java b/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java
index 24b0a2326..f593b0d05 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/SignBlock.java
@@ -15,30 +15,32 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*/
+ */
package com.sk89q.worldedit.blocks;
-import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.data.*;
-import java.util.Map;
import java.util.HashMap;
+import java.util.Map;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.data.DataException;
/**
- *
+ * Represents a sign block.
+ *
* @author sk89q
*/
public class SignBlock extends BaseBlock implements TileEntityBlock {
- /**
- * Stores the sign's text.
- */
+
private String[] text;
/**
* Construct the sign without text.
- *
- * @param type
- * @param data
+ *
+ * @param type type ID
+ * @param data data value (orientation)
*/
public SignBlock(int type, int data) {
super(type, data);
@@ -47,17 +49,22 @@ public class SignBlock extends BaseBlock implements TileEntityBlock {
/**
* Construct the sign with text.
- *
- * @param type
- * @param data
- * @param text
+ *
+ * @param type type ID
+ * @param data data value (orientation)
+ * @param text lines of text
*/
public SignBlock(int type, int data, String[] text) {
super(type, data);
+ if (text == null) {
+ this.text = new String[] { "", "", "", "" };
+ }
this.text = text;
}
/**
+ * Get the text.
+ *
* @return the text
*/
public String[] getText() {
@@ -65,55 +72,52 @@ public class SignBlock extends BaseBlock implements TileEntityBlock {
}
/**
+ * Set the text.
+ *
* @param text the text to set
*/
public void setText(String[] text) {
+ if (text == null) {
+ throw new IllegalArgumentException("Can't set null text for a sign");
+ }
this.text = text;
}
+
+ @Override
+ public boolean hasNbtData() {
+ return true;
+ }
- /**
- * Return the name of the title entity ID.
- *
- * @return title entity ID
- */
- public String getTileEntityID() {
+ @Override
+ public String getNbtId() {
return "Sign";
}
- /**
- * Store additional tile entity data. Returns true if the data is used.
- *
- * @return map of values
- * @throws DataException
- */
- public Map toTileEntityNBT()
- throws DataException {
+ @Override
+ public CompoundTag getNbtData() {
Map values = new HashMap();
values.put("Text1", new StringTag("Text1", text[0]));
values.put("Text2", new StringTag("Text2", text[1]));
values.put("Text3", new StringTag("Text3", text[2]));
values.put("Text4", new StringTag("Text4", text[3]));
- return values;
+ return new CompoundTag(getNbtId(), values);
}
- /**
- * Get additional information from the title entity data.
- *
- * @param values
- * @throws DataException
- */
- public void fromTileEntityNBT(Map values)
- throws DataException {
- if (values == null) {
+ @Override
+ public void setNbtData(CompoundTag rootTag) throws DataException {
+ if (rootTag == null) {
return;
}
+ Map values = rootTag.getValue();
+
Tag t;
text = new String[] { "", "", "", "" };
t = values.get("id");
- if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Sign")) {
+ if (!(t instanceof StringTag)
+ || !((StringTag) t).getValue().equals("Sign")) {
throw new DataException("'Sign' tile entity expected");
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/TileEntityBlock.java b/src/main/java/com/sk89q/worldedit/blocks/TileEntityBlock.java
index eae44de23..11d7fcc2f 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/TileEntityBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/TileEntityBlock.java
@@ -1,7 +1,7 @@
// $Id$
/*
* WorldEdit
- * Copyright (C) 2010 sk89q and contributors
+ * Copyright (C) sk89q and contributors
*
* 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
@@ -19,42 +19,22 @@
package com.sk89q.worldedit.blocks;
-import com.sk89q.jnbt.Tag;
-import com.sk89q.worldedit.data.*;
-
-import java.util.Map;
+import com.sk89q.worldedit.foundation.NbtValued;
/**
- * A class implementing this interface has extra TileEntityBlock data to store.
+ * Indicates a block that contains extra data identified as an NBT structure. Compared
+ * to a {@link NbtValued}, tile entity blocks also contain an ID.
*
+ * @see NbtValued
* @author sk89q
*/
-public interface TileEntityBlock {
+public interface TileEntityBlock extends NbtValued {
/**
* Return the name of the title entity ID.
*
- * @return tile entity ID
+ * @return tile entity ID, non-null string
*/
- public abstract String getTileEntityID();
-
- /**
- * Store additional tile entity data.
- *
- * @return map of values
- * @throws DataException When invalid data is encountered
- */
- public abstract Map toTileEntityNBT()
- throws DataException;
-
- /**
- * Get additional information from the tile entity data.
- *
- * @param values map of data
- * @throws DataException When invalid data is encountered
- */
- public abstract void fromTileEntityNBT(Map values)
- throws DataException;
-
+ String getNbtId();
}
diff --git a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
index 34c160363..9c9c3bd10 100644
--- a/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
+++ b/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
@@ -27,17 +27,20 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
-import com.sk89q.worldedit.LocalEntity;
-import com.sk89q.worldedit.WorldEdit;
-import com.sk89q.worldedit.bukkit.entity.BukkitEntity;
-import com.sk89q.worldedit.util.TreeGenerator;
+import org.bukkit.Effect;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.TreeType;
+import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Chest;
-import org.bukkit.block.Furnace;
import org.bukkit.block.CreatureSpawner;
+import org.bukkit.block.Furnace;
import org.bukkit.block.Sign;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Animals;
@@ -56,24 +59,34 @@ import org.bukkit.entity.Tameable;
import org.bukkit.inventory.DoubleChestInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
-import org.bukkit.Effect;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.TreeType;
-import org.bukkit.World;
import com.sk89q.worldedit.BiomeType;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.EntityType;
+import com.sk89q.worldedit.LocalEntity;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
-import com.sk89q.worldedit.blocks.*;
-import com.sk89q.worldedit.EntityType;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.blocks.BaseItemStack;
+import com.sk89q.worldedit.blocks.BlockID;
+import com.sk89q.worldedit.blocks.ContainerBlock;
+import com.sk89q.worldedit.blocks.FurnaceBlock;
+import com.sk89q.worldedit.blocks.MobSpawnerBlock;
+import com.sk89q.worldedit.blocks.NoteBlock;
+import com.sk89q.worldedit.blocks.SignBlock;
+import com.sk89q.worldedit.bukkit.entity.BukkitEntity;
import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.util.TreeGenerator;
public class BukkitWorld extends LocalWorld {
+
+ private static final Logger logger = Logger.getLogger(BukkitWorld.class.getCanonicalName());
private World world;
+ private boolean skipNmsAccess = false;
+ private boolean skipNmsSafeSet = false;
/**
* Construct the object.
@@ -211,6 +224,7 @@ public class BukkitWorld extends LocalWorld {
* @param pt
* @return
*/
+ @Override
public BiomeType getBiome(Vector2D pt) {
Biome bukkitBiome = world.getBiome(pt.getBlockX(), pt.getBlockZ());
try {
@@ -340,6 +354,15 @@ public class BukkitWorld extends LocalWorld {
return true;
}
+ if (!skipNmsAccess) {
+ try {
+ return NmsBlock.set(world, pt, block);
+ } catch (Throwable t) {
+ logger.log(Level.WARNING, "WorldEdit: Failed to do NMS access for direct NBT data copy", t);
+ skipNmsAccess = true;
+ }
+ }
+
return false;
}
@@ -400,6 +423,7 @@ public class BukkitWorld extends LocalWorld {
org.bukkit.block.NoteBlock bukkit = (org.bukkit.block.NoteBlock) state;
NoteBlock we = (NoteBlock) block;
we.setNote(bukkit.getRawNote());
+ return true;
}
return false;
@@ -902,6 +926,7 @@ public class BukkitWorld extends LocalWorld {
world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally();
}
+ @Override
public LocalEntity[] getEntities(Region region) {
List entities = new ArrayList();
for (Vector2D pt : region.getChunks()) {
@@ -917,6 +942,7 @@ public class BukkitWorld extends LocalWorld {
return entities.toArray(new BukkitEntity[entities.size()]);
}
+ @Override
public int killEntities(LocalEntity... entities) {
int amount = 0;
Set toKill = new HashSet();
@@ -931,4 +957,52 @@ public class BukkitWorld extends LocalWorld {
}
return amount;
}
+
+ @Override
+ public BaseBlock getBlock(Vector pt) {
+ int type = getBlockType(pt);
+ int data = getBlockData(pt);
+
+ switch (type) {
+ case BlockID.WALL_SIGN:
+ case BlockID.SIGN_POST:
+ //case BlockID.CHEST: // Prevent data loss for now
+ //case BlockID.FURNACE:
+ //case BlockID.BURNING_FURNACE:
+ //case BlockID.DISPENSER:
+ //case BlockID.MOB_SPAWNER:
+ case BlockID.NOTE_BLOCK:
+ return super.getBlock(pt);
+ default:
+ if (!skipNmsAccess) {
+ try {
+ NmsBlock block = NmsBlock.get(world, pt, type, data);
+ if (block != null) {
+ return block;
+ }
+ } catch (Throwable t) {
+ logger.log(Level.WARNING,
+ "WorldEdit: Failed to do NMS access for direct NBT data copy", t);
+ skipNmsAccess = true;
+ }
+ }
+ }
+
+ return super.getBlock(pt);
+ }
+
+ @Override
+ public boolean setBlock(Vector pt, com.sk89q.worldedit.foundation.Block block, boolean notifyAdjacent) {
+ if (!skipNmsSafeSet) {
+ try {
+ return NmsBlock.setSafely(this, pt, block, notifyAdjacent);
+ } catch (Throwable t) {
+ logger.log(Level.WARNING,
+ "WorldEdit: Failed to do NMS safe block set", t);
+ skipNmsSafeSet = true;
+ }
+ }
+
+ return super.setBlock(pt, block, notifyAdjacent);
+ }
}
diff --git a/src/main/java/com/sk89q/worldedit/bukkit/NmsBlock.java b/src/main/java/com/sk89q/worldedit/bukkit/NmsBlock.java
new file mode 100644
index 000000000..63b09aa93
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/bukkit/NmsBlock.java
@@ -0,0 +1,360 @@
+// $Id$
+/*
+ * This file is a part of WorldEdit.
+ * Copyright (c) sk89q
+ * Copyright (c) the WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * (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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+*/
+
+package com.sk89q.worldedit.bukkit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.server.NBTBase;
+import net.minecraft.server.NBTTagByte;
+import net.minecraft.server.NBTTagByteArray;
+import net.minecraft.server.NBTTagCompound;
+import net.minecraft.server.NBTTagDouble;
+import net.minecraft.server.NBTTagEnd;
+import net.minecraft.server.NBTTagFloat;
+import net.minecraft.server.NBTTagInt;
+import net.minecraft.server.NBTTagIntArray;
+import net.minecraft.server.NBTTagList;
+import net.minecraft.server.NBTTagLong;
+import net.minecraft.server.NBTTagShort;
+import net.minecraft.server.NBTTagString;
+import net.minecraft.server.TileEntity;
+
+import org.bukkit.World;
+import org.bukkit.craftbukkit.CraftWorld;
+
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.ByteTag;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.DoubleTag;
+import com.sk89q.jnbt.EndTag;
+import com.sk89q.jnbt.FloatTag;
+import com.sk89q.jnbt.IntArrayTag;
+import com.sk89q.jnbt.IntTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.LongTag;
+import com.sk89q.jnbt.NBTConstants;
+import com.sk89q.jnbt.ShortTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.blocks.TileEntityBlock;
+import com.sk89q.worldedit.data.DataException;
+import com.sk89q.worldedit.foundation.Block;
+
+/**
+ * A blind handler of blocks with TileEntity data that directly access Minecraft's
+ * classes through CraftBukkit.
+ *
+ * Usage of this class may break terribly in the future, and therefore usage should
+ * be trapped in a handler for {@link Throwable}.
+ */
+class NmsBlock extends BaseBlock implements TileEntityBlock {
+
+ private NBTTagCompound nbtData = null;
+
+ /**
+ * Create a new instance with a given type ID, data value, and previous
+ * {@link TileEntityBlock}-implementing object.
+ *
+ * @param type block type ID
+ * @param data data value
+ * @param tileEntityBlock tile entity block
+ */
+ public NmsBlock(int type, int data, TileEntityBlock tileEntityBlock) {
+ super(type, data);
+
+ nbtData = (NBTTagCompound) fromNative(tileEntityBlock.getNbtData());
+ }
+
+ /**
+ * Create a new instance with a given type ID, data value, and raw
+ * {@link NBTTagCompound} copy.
+ *
+ * @param type block type ID
+ * @param data data value
+ * @param nbtData raw NBT data
+ */
+ public NmsBlock(int type, int data, NBTTagCompound nbtData) {
+ super(type, data);
+
+ this.nbtData = nbtData;
+ }
+
+ /**
+ * Build a {@link NBTTagCompound} that has valid coordinates.
+ *
+ * @param pt coordinates to set
+ * @return the tag compound
+ */
+ private NBTTagCompound getNmsData(Vector pt) {
+ if (nbtData == null) {
+ return null;
+ }
+
+ nbtData.set("x", new NBTTagInt("x", pt.getBlockX()));
+ nbtData.set("y", new NBTTagInt("y", pt.getBlockY()));
+ nbtData.set("z", new NBTTagInt("z", pt.getBlockZ()));
+
+ return nbtData;
+ }
+
+ @Override
+ public boolean hasNbtData() {
+ return nbtData != null;
+ }
+
+ @Override
+ public String getNbtId() {
+ if (nbtData == null) {
+ return "";
+ }
+
+ return nbtData.getString("id");
+ }
+
+ @Override
+ public CompoundTag getNbtData() {
+ if (nbtData == null) {
+ return new CompoundTag(getNbtId(),
+ new HashMap());
+ }
+ return (CompoundTag) toNative(nbtData);
+ }
+
+ @Override
+ public void setNbtData(CompoundTag tag) throws DataException {
+ if (tag == null) {
+ this.nbtData = null;
+ }
+ this.nbtData = (NBTTagCompound) fromNative(tag);
+ }
+
+ /**
+ * Build an instance from the given information.
+ *
+ * @param world world to get the block from
+ * @param position position to get the block at
+ * @param type type ID of block
+ * @param data data value of block
+ * @return the block, or null
+ */
+ public static NmsBlock get(World world, Vector position, int type, int data) {
+ TileEntity te = ((CraftWorld) world).getHandle().getTileEntity(
+ position.getBlockX(), position.getBlockY(), position.getBlockZ());
+
+ if (te != null) {
+ NBTTagCompound tag = new NBTTagCompound();
+ te.b(tag); // Load data
+ return new NmsBlock(type, data, tag);
+ }
+
+ return null;
+ }
+
+ /**
+ * Set an instance or a {@link TileEntityBlock} to the given position.
+ *
+ * @param world world to set the block in
+ * @param position position to set the block at
+ * @param block the block to set
+ * @return true if tile entity data was copied to the world
+ */
+ public static boolean set(World world, Vector position, BaseBlock block) {
+ NBTTagCompound data = null;
+
+ if (block instanceof NmsBlock) {
+ NmsBlock nmsProxyBlock = (NmsBlock) block;
+ data = nmsProxyBlock.getNmsData(position);
+ } else if (block instanceof TileEntityBlock) {
+ NmsBlock nmsProxyBlock = new NmsBlock(
+ block.getType(), block.getData(), block);
+ data = nmsProxyBlock.getNmsData(position);
+ }
+
+ if (data != null) {
+ TileEntity te = ((CraftWorld) world).getHandle().getTileEntity(
+ position.getBlockX(), position.getBlockY(), position.getBlockZ());
+ if (te != null) {
+ te.a(data); // Load data
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Tries to set a block 'safely', as in setting the block data to the location, and
+ * then triggering physics only at the end.
+ *
+ * @param world world to set the block in
+ * @param position position to set the block at
+ * @param block the block to set
+ * @param notifyAdjacent true to notify physics and what not
+ * @return true if set
+ */
+ public static boolean setSafely(BukkitWorld world, Vector position,
+ Block block, boolean notifyAdjacent) {
+
+ int x = position.getBlockX();
+ int y = position.getBlockY();
+ int z = position.getBlockZ();
+
+ CraftWorld craftWorld = ((CraftWorld) world.getWorld());
+
+ boolean successful = craftWorld.getHandle().setRawTypeIdAndData(
+ x, y, z, block.getId(), block.getData());
+
+ if (successful) {
+ if (block instanceof BaseBlock) {
+ world.copyToWorld(position, (BaseBlock) block);
+ }
+
+ if (notifyAdjacent) {
+ craftWorld.getHandle().update(x, y, z, block.getId());
+ } else {
+ craftWorld.getHandle().notify(x, y, z);
+ }
+ }
+
+ return successful;
+ }
+
+ /**
+ * Converts from a non-native NMS NBT structure to a native WorldEdit NBT
+ * structure.
+ *
+ * @param foreign non-native NMS NBT structure
+ * @return native WorldEdit NBT structure
+ */
+ private static Tag toNative(NBTBase foreign) {
+ if (foreign == null) {
+ return null;
+ }
+ if (foreign instanceof NBTTagCompound) {
+ Map values = new HashMap();
+ for (Object obj : ((NBTTagCompound) foreign).d()) {
+ NBTBase base = (NBTBase) obj;
+ values.put(base.getName(), toNative(base));
+ }
+ return new CompoundTag(foreign.getName(), values);
+ } else if (foreign instanceof NBTTagByte) {
+ return new ByteTag(foreign.getName(), ((NBTTagByte) foreign).data);
+ } else if (foreign instanceof NBTTagByteArray) {
+ return new ByteArrayTag(foreign.getName(),
+ ((NBTTagByteArray) foreign).data);
+ } else if (foreign instanceof NBTTagDouble) {
+ return new DoubleTag(foreign.getName(),
+ ((NBTTagDouble) foreign).data);
+ } else if (foreign instanceof NBTTagFloat) {
+ return new FloatTag(foreign.getName(), ((NBTTagFloat) foreign).data);
+ } else if (foreign instanceof NBTTagInt) {
+ return new IntTag(foreign.getName(), ((NBTTagInt) foreign).data);
+ } else if (foreign instanceof NBTTagIntArray) {
+ return new IntArrayTag(foreign.getName(),
+ ((NBTTagIntArray) foreign).data);
+ } else if (foreign instanceof NBTTagList) {
+ List values = new ArrayList();
+ NBTTagList foreignList = (NBTTagList) foreign;
+ int type = NBTConstants.TYPE_BYTE;
+ for (int i = 0; i < foreignList.size(); i++) {
+ NBTBase foreignTag = foreignList.get(i);
+ values.add(toNative(foreignTag));
+ type = foreignTag.getTypeId();
+ }
+ Class extends Tag> cls = NBTConstants.getClassFromType(type);
+ return new ListTag(foreign.getName(), cls, values);
+ } else if (foreign instanceof NBTTagLong) {
+ return new LongTag(foreign.getName(), ((NBTTagLong) foreign).data);
+ } else if (foreign instanceof NBTTagShort) {
+ return new ShortTag(foreign.getName(), ((NBTTagShort) foreign).data);
+ } else if (foreign instanceof NBTTagString) {
+ return new StringTag(foreign.getName(),
+ ((NBTTagString) foreign).data);
+ } else if (foreign instanceof NBTTagEnd) {
+ return new EndTag();
+ } else {
+ throw new IllegalArgumentException("Don't know how to make native "
+ + foreign.getClass().getCanonicalName());
+ }
+ }
+
+ /**
+ * Converts a WorldEdit-native NBT structure to a NMS structure.
+ *
+ * @param foreign structure to convert
+ * @return non-native structure
+ */
+ private static NBTBase fromNative(Tag foreign) {
+ if (foreign == null) {
+ return null;
+ }
+ if (foreign instanceof CompoundTag) {
+ NBTTagCompound tag = new NBTTagCompound(foreign.getName());
+ for (Map.Entry entry : ((CompoundTag) foreign)
+ .getValue().entrySet()) {
+ tag.set(entry.getKey(), fromNative(entry.getValue()));
+ }
+ return tag;
+ } else if (foreign instanceof ByteTag) {
+ return new NBTTagByte(foreign.getName(),
+ ((ByteTag) foreign).getValue());
+ } else if (foreign instanceof ByteArrayTag) {
+ return new NBTTagByteArray(foreign.getName(),
+ ((ByteArrayTag) foreign).getValue());
+ } else if (foreign instanceof DoubleTag) {
+ return new NBTTagDouble(foreign.getName(),
+ ((DoubleTag) foreign).getValue());
+ } else if (foreign instanceof FloatTag) {
+ return new NBTTagFloat(foreign.getName(),
+ ((FloatTag) foreign).getValue());
+ } else if (foreign instanceof IntTag) {
+ return new NBTTagInt(foreign.getName(),
+ ((IntTag) foreign).getValue());
+ } else if (foreign instanceof IntArrayTag) {
+ return new NBTTagIntArray(foreign.getName(),
+ ((IntArrayTag) foreign).getValue());
+ } else if (foreign instanceof ListTag) {
+ NBTTagList tag = new NBTTagList(foreign.getName());
+ ListTag foreignList = (ListTag) foreign;
+ for (Tag t : foreignList.getValue()) {
+ tag.add(fromNative(t));
+ }
+ return tag;
+ } else if (foreign instanceof LongTag) {
+ return new NBTTagLong(foreign.getName(),
+ ((LongTag) foreign).getValue());
+ } else if (foreign instanceof ShortTag) {
+ return new NBTTagShort(foreign.getName(),
+ ((ShortTag) foreign).getValue());
+ } else if (foreign instanceof StringTag) {
+ return new NBTTagString(foreign.getName(),
+ ((StringTag) foreign).getValue());
+ } else if (foreign instanceof EndTag) {
+ return new NBTTagEnd();
+ } else {
+ throw new IllegalArgumentException("Don't know how to make NMS "
+ + foreign.getClass().getCanonicalName());
+ }
+ }
+}
diff --git a/src/main/java/com/sk89q/worldedit/data/AnvilChunk.java b/src/main/java/com/sk89q/worldedit/data/AnvilChunk.java
index e92e2d4f0..8605c9be3 100644
--- a/src/main/java/com/sk89q/worldedit/data/AnvilChunk.java
+++ b/src/main/java/com/sk89q/worldedit/data/AnvilChunk.java
@@ -182,12 +182,12 @@ public class AnvilChunk implements Chunk {
* @return
* @throws DataException
*/
- private Map getBlockTileEntity(Vector pos) throws DataException {
+ private CompoundTag getBlockTileEntity(Vector pos) throws DataException {
if (tileEntities == null) {
populateTileEntities();
}
- return tileEntities.get(new BlockVector(pos));
+ return new CompoundTag("", tileEntities.get(new BlockVector(pos)));
}
@Override
@@ -213,8 +213,8 @@ public class AnvilChunk implements Chunk {
}
if (block instanceof TileEntityBlock) {
- Map tileEntity = getBlockTileEntity(pos);
- ((TileEntityBlock) block).fromTileEntityNBT(tileEntity);
+ CompoundTag tileEntity = getBlockTileEntity(pos);
+ ((TileEntityBlock) block).setNbtData(tileEntity);
}
return block;
diff --git a/src/main/java/com/sk89q/worldedit/data/OldChunk.java b/src/main/java/com/sk89q/worldedit/data/OldChunk.java
index 23ece3928..9f7bd3402 100644
--- a/src/main/java/com/sk89q/worldedit/data/OldChunk.java
+++ b/src/main/java/com/sk89q/worldedit/data/OldChunk.java
@@ -19,12 +19,28 @@
package com.sk89q.worldedit.data;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.HashMap;
-import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.*;
-import com.sk89q.worldedit.blocks.*;
+
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.IntTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.BlockVector;
+import com.sk89q.worldedit.LocalWorld;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.blocks.BlockID;
+import com.sk89q.worldedit.blocks.ChestBlock;
+import com.sk89q.worldedit.blocks.DispenserBlock;
+import com.sk89q.worldedit.blocks.FurnaceBlock;
+import com.sk89q.worldedit.blocks.MobSpawnerBlock;
+import com.sk89q.worldedit.blocks.NoteBlock;
+import com.sk89q.worldedit.blocks.SignBlock;
+import com.sk89q.worldedit.blocks.TileEntityBlock;
/**
* Represents a chunk.
@@ -164,12 +180,12 @@ public class OldChunk implements Chunk {
* @return
* @throws DataException
*/
- private Map getBlockTileEntity(Vector pos) throws DataException {
+ private CompoundTag getBlockTileEntity(Vector pos) throws DataException {
if (tileEntities == null) {
populateTileEntities();
}
- return tileEntities.get(new BlockVector(pos));
+ return new CompoundTag("", tileEntities.get(new BlockVector(pos)));
}
@Override
@@ -195,8 +211,8 @@ public class OldChunk implements Chunk {
}
if (block instanceof TileEntityBlock) {
- Map tileEntity = getBlockTileEntity(pos);
- ((TileEntityBlock) block).fromTileEntityNBT(tileEntity);
+ CompoundTag tileEntity = getBlockTileEntity(pos);
+ ((TileEntityBlock) block).setNbtData(tileEntity);
}
return block;
diff --git a/src/main/java/com/sk89q/worldedit/foundation/Block.java b/src/main/java/com/sk89q/worldedit/foundation/Block.java
index 3f77873d1..a155f3198 100644
--- a/src/main/java/com/sk89q/worldedit/foundation/Block.java
+++ b/src/main/java/com/sk89q/worldedit/foundation/Block.java
@@ -16,7 +16,6 @@
* this program. If not, see .
*/
-
package com.sk89q.worldedit.foundation;
import com.sk89q.jnbt.CompoundTag;
@@ -34,7 +33,7 @@ import com.sk89q.worldedit.data.DataException;
* Implementations can and should extend this class to allow native implementations
* of NBT data handling, primarily for performance reasons. Subclasses can only convert
* from and to WorldEdit-native NBT structures when absolutely necessary (a.k.a. when
- * {@link #getNbtData()} and {@link #setNbtData(CompoundTag)} are called. When
+ * {@link #getNbtData()} and {@link #setNbtData(CompoundTag)} are called). When
* overriding the NBT methods, {@link #getNbtId()} should be overridden too, otherwise
* the default implementation will invoke {@link #getNbtData()}, a potentially costly
* operation when it is not needed. Implementations may want to cache converted NBT data
@@ -64,7 +63,8 @@ public class Block implements TileEntityBlock {
// Instances of this class should be _as small as possible_ because there will
// be millions of instances of this object.
- private short rawIdData;
+ private short id;
+ private short data;
private CompoundTag nbtData;
/**
@@ -114,7 +114,7 @@ public class Block implements TileEntityBlock {
* @return ID (between 0 and {@link #MAX_ID})
*/
public int getId() {
- return rawIdData >> 4;
+ return id;
}
/**
@@ -123,15 +123,16 @@ public class Block implements TileEntityBlock {
* @param id block id (between 0 and {@link #MAX_ID}).
*/
public void setId(int id) {
- if (id < MAX_ID) {
- throw new IllegalArgumentException("Can't have a block ID above " + MAX_ID);
+ if (id > MAX_ID) {
+ throw new IllegalArgumentException("Can't have a block ID above "
+ + MAX_ID + " (" + id + " given)");
}
-
+
if (id < 0) {
throw new IllegalArgumentException("Can't have a block ID below 0");
}
- rawIdData = (short) ((id << 4) | rawIdData & 0xf);
+ this.id = (short) id;
}
/**
@@ -140,7 +141,7 @@ public class Block implements TileEntityBlock {
* @return data value (0-15)
*/
public int getData() {
- return rawIdData & 0xf;
+ return data;
}
/**
@@ -149,15 +150,17 @@ public class Block implements TileEntityBlock {
* @param data block data value (between 0 and {@link #MAX_DATA}).
*/
public void setData(int data) {
- if (data < MAX_DATA) {
- throw new IllegalArgumentException("Can't have a block data value above " + MAX_DATA);
+ if (data > MAX_DATA) {
+ throw new IllegalArgumentException(
+ "Can't have a block data value above " + MAX_DATA + " ("
+ + data + " given)");
}
if (data < 0) {
throw new IllegalArgumentException("Can't have a block data value below 0");
}
- rawIdData = (short) ((rawIdData ^ 4) | data);
+ this.data = (short) data;
}
/**
@@ -173,20 +176,11 @@ public class Block implements TileEntityBlock {
setData(data);
}
- /**
- * Returns whether the block contains NBT data.
- *
- * @return NBT data;
- */
+ @Override
public boolean hasNbtData() {
return getNbtData() != null;
}
- /**
- * Gets the ID of the NBT data (tile entity data).
- *
- * @return ID value (may be blank), or an empty string if no NBT data is set
- */
@Override
public String getNbtId() {
CompoundTag nbtData = getNbtData();
diff --git a/src/main/java/com/sk89q/worldedit/foundation/NbtValued.java b/src/main/java/com/sk89q/worldedit/foundation/NbtValued.java
index 8236fdc0f..89dcd2069 100644
--- a/src/main/java/com/sk89q/worldedit/foundation/NbtValued.java
+++ b/src/main/java/com/sk89q/worldedit/foundation/NbtValued.java
@@ -27,12 +27,22 @@ import com.sk89q.worldedit.data.DataException;
* be used in other cases.
*/
public interface NbtValued {
+
+ /**
+ * Returns whether the block contains NBT data. {@link #getNbtData()} must not return
+ * null if this method returns true.
+ *
+ * @return true if there is NBT data
+ */
+ public boolean hasNbtData();
/**
* Get the object's NBT data (tile entity data). The returned tag, if modified
* in any way, should be sent to {@link #setNbtData(CompoundTag)} so that
* the instance knows of the changes. Making changes without calling
* {@link #setNbtData(CompoundTag)} could have unintended consequences.
+ *
+ * {@link #hasNbtData()} must return true if and only if method does not return null.
*
* @return compound tag, or null
*/
diff --git a/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java
index cc932076e..2fb408bd9 100644
--- a/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java
+++ b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java
@@ -18,6 +18,18 @@
package com.sk89q.worldedit.schematic;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.zip.GZIPInputStream;
+
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
@@ -35,17 +47,6 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.data.DataException;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-
/**
* @author zml2008
*/
@@ -176,7 +177,7 @@ public class MCEditSchematicFormat extends SchematicFormat {
BaseBlock block = getBlockForId(blocks[index], blockData[index]);
if (block instanceof TileEntityBlock && tileEntitiesMap.containsKey(pt)) {
- ((TileEntityBlock) block).fromTileEntityNBT(tileEntitiesMap.get(pt));
+ ((TileEntityBlock) block).setNbtData(new CompoundTag("", tileEntitiesMap.get(pt)));
}
clipboard.setBlock(pt, block);
}
@@ -239,19 +240,22 @@ public class MCEditSchematicFormat extends SchematicFormat {
// Store TileEntity data
if (block instanceof TileEntityBlock) {
- TileEntityBlock tileEntityBlock =
- (TileEntityBlock) block;
+ TileEntityBlock tileEntityBlock = block;
// Get the list of key/values from the block
- Map values = tileEntityBlock.toTileEntityNBT();
- if (values != null) {
- values.put("id", new StringTag("id",
- tileEntityBlock.getTileEntityID()));
+ CompoundTag rawTag = tileEntityBlock.getNbtData();
+ if (rawTag != null) {
+ Map values = new HashMap();
+ for (Entry entry : rawTag.getValue().entrySet()) {
+ values.put(entry.getKey(), entry.getValue());
+ }
+
+ values.put("id", new StringTag("id", tileEntityBlock.getNbtId()));
values.put("x", new IntTag("x", x));
values.put("y", new IntTag("y", y));
values.put("z", new IntTag("z", z));
- CompoundTag tileEntityTag =
- new CompoundTag("TileEntity", values);
+
+ CompoundTag tileEntityTag = new CompoundTag("TileEntity", values);
tileEntities.add(tileEntityTag);
}
}