diff --git a/src/main/java/com/sk89q/jnbt/IntArrayTag.java b/src/main/java/com/sk89q/jnbt/IntArrayTag.java
new file mode 100644
index 000000000..4a3365bd5
--- /dev/null
+++ b/src/main/java/com/sk89q/jnbt/IntArrayTag.java
@@ -0,0 +1,87 @@
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
+
+/*
+ * JNBT License
+ *
+ * Copyright (c) 2010 Graham Edgecombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the JNBT team nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * The TAG_Int_Array
tag.
+ *
+ * @author Graham Edgecombe
+ *
+ */
+public final class IntArrayTag extends Tag {
+
+ /**
+ * The value.
+ */
+ private final int[] value;
+
+ /**
+ * Creates the tag.
+ *
+ * @param name
+ * The name.
+ * @param value
+ * The value.
+ */
+ public IntArrayTag(String name, int[] value) {
+ super(name);
+ this.value = value;
+ }
+
+ @Override
+ public int[] getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder hex = new StringBuilder();
+ for (int b : value) {
+ String hexDigits = Integer.toHexString(b).toUpperCase();
+ if (hexDigits.length() == 1) {
+ hex.append("0");
+ }
+ hex.append(hexDigits).append(" ");
+ }
+ String name = getName();
+ String append = "";
+ if (name != null && !name.equals("")) {
+ append = "(\"" + this.getName() + "\")";
+ }
+ return "TAG_Int_Array" + append + ": " + hex.toString();
+ }
+
+}
diff --git a/src/main/java/com/sk89q/jnbt/NBTConstants.java b/src/main/java/com/sk89q/jnbt/NBTConstants.java
index b8fe8d105..b7b3adb19 100644
--- a/src/main/java/com/sk89q/jnbt/NBTConstants.java
+++ b/src/main/java/com/sk89q/jnbt/NBTConstants.java
@@ -54,7 +54,7 @@ public final class NBTConstants {
public static final int TYPE_END = 0, TYPE_BYTE = 1, TYPE_SHORT = 2,
TYPE_INT = 3, TYPE_LONG = 4, TYPE_FLOAT = 5, TYPE_DOUBLE = 6,
TYPE_BYTE_ARRAY = 7, TYPE_STRING = 8, TYPE_LIST = 9,
- TYPE_COMPOUND = 10;
+ TYPE_COMPOUND = 10, TYPE_INT_ARRAY = 11;
/**
* Default private constructor.
diff --git a/src/main/java/com/sk89q/jnbt/NBTInputStream.java b/src/main/java/com/sk89q/jnbt/NBTInputStream.java
index 6ed486163..6dc92ada5 100644
--- a/src/main/java/com/sk89q/jnbt/NBTInputStream.java
+++ b/src/main/java/com/sk89q/jnbt/NBTInputStream.java
@@ -199,6 +199,13 @@ public final class NBTInputStream implements Closeable {
}
return new CompoundTag(name, tagMap);
+ case NBTConstants.TYPE_INT_ARRAY:
+ length = is.readInt();
+ int[] data = new int[length];
+ for (int i = 0; i < length; i++) {
+ data[i] = is.readInt();
+ }
+ return new IntArrayTag(name, data);
default:
throw new IOException("Invalid tag type: " + type + ".");
}
diff --git a/src/main/java/com/sk89q/jnbt/NBTOutputStream.java b/src/main/java/com/sk89q/jnbt/NBTOutputStream.java
index e4f81da18..4cd9935dd 100644
--- a/src/main/java/com/sk89q/jnbt/NBTOutputStream.java
+++ b/src/main/java/com/sk89q/jnbt/NBTOutputStream.java
@@ -157,6 +157,8 @@ public final class NBTOutputStream implements Closeable {
case NBTConstants.TYPE_COMPOUND:
writeCompoundTagPayload((CompoundTag) tag);
break;
+ case NBTConstants.TYPE_INT_ARRAY:
+ writeIntArrayTagPayload((IntArrayTag) tag);
default:
throw new IOException("Invalid tag type: " + type + ".");
}
@@ -308,6 +310,14 @@ public final class NBTOutputStream implements Closeable {
private void writeEndTagPayload(EndTag tag) {
/* empty */
}
+
+ private void writeIntArrayTagPayload(IntArrayTag tag) throws IOException {
+ int[] data = tag.getValue();
+ os.writeInt(data.length);
+ for (int i = 0; i < data.length; i++) {
+ os.writeInt(data[i]);
+ }
+ }
public void close() throws IOException {
os.close();
diff --git a/src/main/java/com/sk89q/jnbt/NBTUtils.java b/src/main/java/com/sk89q/jnbt/NBTUtils.java
index 8c217497a..c2c8fc9aa 100644
--- a/src/main/java/com/sk89q/jnbt/NBTUtils.java
+++ b/src/main/java/com/sk89q/jnbt/NBTUtils.java
@@ -1,5 +1,7 @@
package com.sk89q.jnbt;
+import java.util.Map;
+
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
@@ -13,6 +15,7 @@ import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.data.InvalidFormatException;
/*
* JNBT License
@@ -85,6 +88,8 @@ public final class NBTUtils {
return "TAG_Short";
} else if (clazz.equals(StringTag.class)) {
return "TAG_String";
+ } else if (clazz.equals(IntArrayTag.class)) {
+ return "TAG_Int_Array";
} else {
throw new IllegalArgumentException("Invalid tag classs ("
+ clazz.getName() + ").");
@@ -123,6 +128,8 @@ public final class NBTUtils {
return NBTConstants.TYPE_SHORT;
} else if (clazz.equals(StringTag.class)) {
return NBTConstants.TYPE_STRING;
+ } else if (clazz.equals(IntArrayTag.class)) {
+ return NBTConstants.TYPE_INT_ARRAY;
} else {
throw new IllegalArgumentException("Invalid tag classs ("
+ clazz.getName() + ").");
@@ -162,6 +169,8 @@ public final class NBTUtils {
return ListTag.class;
case NBTConstants.TYPE_COMPOUND:
return CompoundTag.class;
+ case NBTConstants.TYPE_INT_ARRAY:
+ return IntArrayTag.class;
default:
throw new IllegalArgumentException("Invalid tag type : " + type
+ ".");
@@ -174,5 +183,26 @@ public final class NBTUtils {
private NBTUtils() {
}
+
+ /**
+ * Get child tag of a NBT structure.
+ *
+ * @param items
+ * @param key
+ * @param expected
+ * @return child tag
+ * @throws InvalidFormatException
+ */
+ public static T getChildTag(Map items, String key,
+ Class expected) throws InvalidFormatException {
+ if (!items.containsKey(key)) {
+ throw new InvalidFormatException("Missing a \"" + key + "\" tag");
+ }
+ Tag tag = items.get(key);
+ if (!expected.isInstance(tag)) {
+ throw new InvalidFormatException(key + " tag is not of tag type " + expected.getName());
+ }
+ return expected.cast(tag);
+ }
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java b/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java
index 2b78d0d0d..020233d90 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/ChestBlock.java
@@ -150,7 +150,7 @@ public class ChestBlock extends BaseBlock implements TileEntityBlock, ContainerB
throw new DataException("'Chest' tile entity expected");
}
- ListTag items = (ListTag) Chunk.getChildTag(values, "Items", ListTag.class);
+ ListTag items = (ListTag) NBTUtils.getChildTag(values, "Items", ListTag.class);
BaseItemStack[] newItems = new BaseItemStack[27];
for (Tag tag : items.getValue()) {
@@ -161,20 +161,20 @@ public class ChestBlock extends BaseBlock implements TileEntityBlock, ContainerB
CompoundTag item = (CompoundTag) tag;
Map itemValues = item.getValue();
- short id = Chunk.getChildTag(itemValues, "id", ShortTag.class).getValue();
- short damage = Chunk.getChildTag(itemValues, "Damage", ShortTag.class).getValue();
- byte count = Chunk.getChildTag(itemValues, "Count", ByteTag.class).getValue();
- byte slot = Chunk.getChildTag(itemValues, "Slot", ByteTag.class).getValue();
+ short id = NBTUtils.getChildTag(itemValues, "id", ShortTag.class).getValue();
+ short damage = NBTUtils.getChildTag(itemValues, "Damage", ShortTag.class).getValue();
+ byte count = NBTUtils.getChildTag(itemValues, "Count", ByteTag.class).getValue();
+ byte slot = NBTUtils.getChildTag(itemValues, "Slot", ByteTag.class).getValue();
if (slot >= 0 && slot <= 26) {
BaseItemStack itemstack = new BaseItemStack(id, count, damage);
if(itemValues.containsKey("tag")) {
- ListTag ench = (ListTag) Chunk.getChildTag(itemValues, "tag", CompoundTag.class).getValue().get("ench");
+ ListTag ench = (ListTag) NBTUtils.getChildTag(itemValues, "tag", CompoundTag.class).getValue().get("ench");
for(Tag e : ench.getValue()) {
Map vars = ((CompoundTag) e).getValue();
- short enchid = Chunk.getChildTag(vars, "id", ShortTag.class).getValue();
- short enchlvl = Chunk.getChildTag(vars, "lvl", ShortTag.class).getValue();
+ short enchid = NBTUtils.getChildTag(vars, "id", ShortTag.class).getValue();
+ short enchlvl = NBTUtils.getChildTag(vars, "lvl", ShortTag.class).getValue();
itemstack.getEnchantments().put((int) enchid, (int)enchlvl);
}
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java b/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java
index 46d210f4a..7b7cc73b2 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/DispenserBlock.java
@@ -150,7 +150,7 @@ public class DispenserBlock extends BaseBlock implements TileEntityBlock, Contai
throw new DataException("'Trap' tile entity expected");
}
- ListTag items = (ListTag) Chunk.getChildTag(values, "Items", ListTag.class);
+ ListTag items = (ListTag) NBTUtils.getChildTag(values, "Items", ListTag.class);
BaseItemStack[] newItems = new BaseItemStack[9];
for (Tag tag : items.getValue()) {
@@ -161,20 +161,20 @@ public class DispenserBlock extends BaseBlock implements TileEntityBlock, Contai
CompoundTag item = (CompoundTag) tag;
Map itemValues = item.getValue();
- short id = Chunk.getChildTag(itemValues, "id", ShortTag.class).getValue();
- short damage = Chunk.getChildTag(itemValues, "Damage", ShortTag.class).getValue();
- byte count = Chunk.getChildTag(itemValues, "Count", ByteTag.class).getValue();
- byte slot = Chunk.getChildTag(itemValues, "Slot", ByteTag.class).getValue();
+ short id = NBTUtils.getChildTag(itemValues, "id", ShortTag.class).getValue();
+ short damage = NBTUtils.getChildTag(itemValues, "Damage", ShortTag.class).getValue();
+ byte count = NBTUtils.getChildTag(itemValues, "Count", ByteTag.class).getValue();
+ byte slot = NBTUtils.getChildTag(itemValues, "Slot", ByteTag.class).getValue();
if (slot >= 0 && slot <= 8) {
BaseItemStack itemstack = new BaseItemStack(id, count, damage);
if(itemValues.containsKey("tag")) {
- ListTag ench = (ListTag) Chunk.getChildTag(itemValues, "tag", CompoundTag.class).getValue().get("ench");
+ ListTag ench = (ListTag) NBTUtils.getChildTag(itemValues, "tag", CompoundTag.class).getValue().get("ench");
for(Tag e : ench.getValue()) {
Map vars = ((CompoundTag) e).getValue();
- short enchid = Chunk.getChildTag(vars, "id", ShortTag.class).getValue();
- short enchlvl = Chunk.getChildTag(vars, "lvl", ShortTag.class).getValue();
+ short enchid = NBTUtils.getChildTag(vars, "id", ShortTag.class).getValue();
+ short enchlvl = NBTUtils.getChildTag(vars, "lvl", ShortTag.class).getValue();
itemstack.getEnchantments().put((int) enchid, (int)enchlvl);
}
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java b/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java
index af1e86489..e62d329e8 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/FurnaceBlock.java
@@ -194,7 +194,7 @@ public class FurnaceBlock extends BaseBlock implements TileEntityBlock, Containe
throw new DataException("'Furnace' tile entity expected");
}
- ListTag items = (ListTag) Chunk.getChildTag(values, "Items", ListTag.class);
+ ListTag items = (ListTag) NBTUtils.getChildTag(values, "Items", ListTag.class);
BaseItemStack[] newItems = new BaseItemStack[3];
for (Tag tag : items.getValue()) {
@@ -205,20 +205,20 @@ public class FurnaceBlock extends BaseBlock implements TileEntityBlock, Containe
CompoundTag item = (CompoundTag) tag;
Map itemValues = item.getValue();
- short id = Chunk.getChildTag(itemValues, "id", ShortTag.class).getValue();
- short damage = Chunk.getChildTag(itemValues, "Damage", ShortTag.class).getValue();
- byte count = Chunk.getChildTag(itemValues, "Count", ByteTag.class).getValue();
- byte slot = Chunk.getChildTag(itemValues, "Slot", ByteTag.class).getValue();
+ short id = NBTUtils.getChildTag(itemValues, "id", ShortTag.class).getValue();
+ short damage = NBTUtils.getChildTag(itemValues, "Damage", ShortTag.class).getValue();
+ byte count = NBTUtils.getChildTag(itemValues, "Count", ByteTag.class).getValue();
+ byte slot = NBTUtils.getChildTag(itemValues, "Slot", ByteTag.class).getValue();
if (slot >= 0 && slot <= 2) {
BaseItemStack itemstack = new BaseItemStack(id, count, damage);
if(itemValues.containsKey("tag")) {
- ListTag ench = (ListTag) Chunk.getChildTag(itemValues, "tag", CompoundTag.class).getValue().get("ench");
+ ListTag ench = (ListTag) NBTUtils.getChildTag(itemValues, "tag", CompoundTag.class).getValue().get("ench");
for(Tag e : ench.getValue()) {
Map vars = ((CompoundTag) e).getValue();
- short enchid = Chunk.getChildTag(vars, "id", ShortTag.class).getValue();
- short enchlvl = Chunk.getChildTag(vars, "lvl", ShortTag.class).getValue();
+ short enchid = NBTUtils.getChildTag(vars, "id", ShortTag.class).getValue();
+ short enchlvl = NBTUtils.getChildTag(vars, "lvl", ShortTag.class).getValue();
itemstack.getEnchantments().put((int) enchid, (int)enchlvl);
}
}
diff --git a/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
index be0e519c4..2430502bc 100644
--- a/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
+++ b/src/main/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
@@ -151,8 +151,8 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
throw new DataException("'MobSpawner' tile entity expected");
}
- StringTag mobTypeTag = (StringTag) Chunk.getChildTag(values, "EntityId", StringTag.class);
- ShortTag delayTag = (ShortTag) Chunk.getChildTag(values, "Delay", ShortTag.class);
+ StringTag mobTypeTag = (StringTag) NBTUtils.getChildTag(values, "EntityId", StringTag.class);
+ ShortTag delayTag = (ShortTag) NBTUtils.getChildTag(values, "Delay", ShortTag.class);
this.mobType = mobTypeTag.getValue();
this.delay = delayTag.getValue();
diff --git a/src/main/java/com/sk89q/worldedit/data/AnvilChunk.java b/src/main/java/com/sk89q/worldedit/data/AnvilChunk.java
new file mode 100644
index 000000000..e92e2d4f0
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/data/AnvilChunk.java
@@ -0,0 +1,223 @@
+package com.sk89q.worldedit.data;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.ByteTag;
+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;
+
+public class AnvilChunk implements Chunk {
+
+ private CompoundTag rootTag;
+ private byte[][] blocks;
+ private byte[][] data;
+ private int rootX;
+ private int rootZ;
+
+ private Map> tileEntities;
+ @SuppressWarnings("unused")
+ private LocalWorld world; // TODO: remove if stays unused.
+
+ /**
+ * Construct the chunk with a compound tag.
+ *
+ * @param tag
+ * @throws DataException
+ */
+ public AnvilChunk(LocalWorld world, CompoundTag tag) throws DataException {
+ rootTag = tag;
+ this.world = world;
+
+ rootX = NBTUtils.getChildTag( rootTag.getValue(), "xPos", IntTag.class).getValue();
+ rootZ = NBTUtils.getChildTag( rootTag.getValue(), "zPos", IntTag.class).getValue();
+
+ blocks = new byte[16][16*16*16];
+ data = new byte[16][16*16*8];
+ List sections = NBTUtils.getChildTag(rootTag.getValue(), "Sections", ListTag.class).getValue();
+ for(Tag section : sections) {
+ if(!(section instanceof CompoundTag)) continue;
+ CompoundTag compoundsection = (CompoundTag) section;
+ if(!compoundsection.getValue().containsKey("Y")) continue; // Empty section.
+ int y = NBTUtils.getChildTag(compoundsection.getValue(), "Y", ByteTag.class).getValue();
+ if(y < 0 || y >= 16) continue;
+ blocks[y] = NBTUtils.getChildTag(compoundsection.getValue(), "Blocks", ByteArrayTag.class).getValue();
+ data[y] = NBTUtils.getChildTag(compoundsection.getValue(), "Data", ByteArrayTag.class).getValue();
+ }
+
+ int sectionsize = 16*16*16;
+ for(int i = 0; i < blocks.length; i++) {
+ if (blocks[i].length != sectionsize) {
+ throw new InvalidFormatException("Chunk blocks byte array expected "
+ + "to be " + sectionsize + " bytes; found " + blocks[i].length);
+ }
+ }
+
+ for(int i = 0; i < data.length; i++) {
+ if (data[i].length != (sectionsize/2)) {
+ throw new InvalidFormatException("Chunk block data byte array "
+ + "expected to be " + sectionsize + " bytes; found " + data[i].length);
+ }
+ }
+ }
+
+ @Override
+ public int getBlockID(Vector pos) throws DataException {
+ int x = pos.getBlockX() - rootX * 16;
+ int y = pos.getBlockY();
+ int z = pos.getBlockZ() - rootZ * 16;
+
+ int section = y >> 4;
+ if(section < 0 || section >= blocks.length) throw new DataException("Chunk does not contain position " + pos);
+ int yindex = y & 0x0F;
+ if(yindex < 0 || yindex >= 16) throw new DataException("Chunk does not contain position " + pos);
+
+
+ int index = x + (z * 16 + (yindex * 16 * 16));
+ try {
+ return blocks[section][index];
+ } catch (IndexOutOfBoundsException e) {
+ throw new DataException("Chunk does not contain position " + pos);
+ }
+ }
+
+ @Override
+ public int getBlockData(Vector pos) throws DataException {
+ int x = pos.getBlockX() - rootX * 16;
+ int y = pos.getBlockY();
+ int z = pos.getBlockZ() - rootZ * 16;
+
+ int section = y >> 4;
+ if(section < 0 || section >= blocks.length) throw new DataException("Chunk does not contain position " + pos);
+ int yindex = y & 0x0F;
+ if(yindex < 0 || yindex >= 16) throw new DataException("Chunk does not contain position " + pos);
+
+
+ int index = x + (z * 16 + (yindex * 16 * 16));
+ boolean shift = index % 2 == 0;
+ index /= 2;
+
+ try {
+ if (!shift) {
+ return (data[section][index] & 0xF0) >> 4;
+ } else {
+ return data[section][index] & 0xF;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new DataException("Chunk does not contain position " + pos);
+ }
+ }
+
+ /**
+ * Used to load the tile entities.
+ *
+ * @throws DataException
+ */
+ private void populateTileEntities() throws DataException {
+ List tags = NBTUtils.getChildTag(
+ rootTag.getValue(), "TileEntities", ListTag.class)
+ .getValue();
+
+ tileEntities = new HashMap>();
+
+ for (Tag tag : tags) {
+ if (!(tag instanceof CompoundTag)) {
+ throw new InvalidFormatException("CompoundTag expected in TileEntities");
+ }
+
+ CompoundTag t = (CompoundTag) tag;
+
+ int x = 0;
+ int y = 0;
+ int z = 0;
+
+ Map values = new HashMap();
+
+ for (Map.Entry entry : t.getValue().entrySet()) {
+ if (entry.getKey().equals("x")) {
+ if (entry.getValue() instanceof IntTag) {
+ x = ((IntTag) entry.getValue()).getValue();
+ }
+ } else if (entry.getKey().equals("y")) {
+ if (entry.getValue() instanceof IntTag) {
+ y = ((IntTag) entry.getValue()).getValue();
+ }
+ } else if (entry.getKey().equals("z")) {
+ if (entry.getValue() instanceof IntTag) {
+ z = ((IntTag) entry.getValue()).getValue();
+ }
+ }
+
+ values.put(entry.getKey(), entry.getValue());
+ }
+
+ BlockVector vec = new BlockVector(x, y, z);
+ tileEntities.put(vec, values);
+ }
+ }
+
+ /**
+ * Get the map of tags keyed to strings for a block's tile entity data. May
+ * return null if there is no tile entity data. Not public yet because
+ * what this function returns isn't ideal for usage.
+ *
+ * @param pos
+ * @return
+ * @throws DataException
+ */
+ private Map getBlockTileEntity(Vector pos) throws DataException {
+ if (tileEntities == null) {
+ populateTileEntities();
+ }
+
+ return tileEntities.get(new BlockVector(pos));
+ }
+
+ @Override
+ public BaseBlock getBlock(Vector pos) throws DataException {
+ int id = getBlockID(pos);
+ int data = getBlockData(pos);
+ BaseBlock block;
+
+ if (id == BlockID.WALL_SIGN || id == BlockID.SIGN_POST) {
+ block = new SignBlock(id, data);
+ } else if (id == BlockID.CHEST) {
+ block = new ChestBlock(data);
+ } else if (id == BlockID.FURNACE || id == BlockID.BURNING_FURNACE) {
+ block = new FurnaceBlock(id, data);
+ } else if (id == BlockID.DISPENSER) {
+ block = new DispenserBlock(data);
+ } else if (id == BlockID.MOB_SPAWNER) {
+ block = new MobSpawnerBlock(data);
+ } else if (id == BlockID.NOTE_BLOCK) {
+ block = new NoteBlock(data);
+ } else {
+ block = new BaseBlock(id, data);
+ }
+
+ if (block instanceof TileEntityBlock) {
+ Map tileEntity = getBlockTileEntity(pos);
+ ((TileEntityBlock) block).fromTileEntityNBT(tileEntity);
+ }
+
+ return block;
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/data/Chunk.java b/src/main/java/com/sk89q/worldedit/data/Chunk.java
index a33d5d7f4..e0fd98867 100644
--- a/src/main/java/com/sk89q/worldedit/data/Chunk.java
+++ b/src/main/java/com/sk89q/worldedit/data/Chunk.java
@@ -1,75 +1,9 @@
-// $Id$
-/*
- * WorldEdit
- * Copyright (C) 2010 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
- * 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.data;
-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.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
-/**
- * Represents a chunk.
- *
- * @author sk89q
- */
-public class Chunk {
- private CompoundTag rootTag;
- private byte[] blocks;
- private byte[] data;
- private int rootX;
- private int rootZ;
-
- private Map> tileEntities;
- private LocalWorld world;
-
- /**
- * Construct the chunk with a compound tag.
- *
- * @param tag
- * @throws DataException
- */
- public Chunk(LocalWorld world, CompoundTag tag) throws DataException {
- rootTag = tag;
- this.world = world;
-
- blocks = getChildTag(
- rootTag.getValue(), "Blocks", ByteArrayTag.class).getValue();
- data = getChildTag(
- rootTag.getValue(), "Data", ByteArrayTag.class).getValue();
- rootX = getChildTag(
- rootTag.getValue(), "xPos", IntTag.class).getValue();
- rootZ = getChildTag(
- rootTag.getValue(), "zPos", IntTag.class).getValue();
-
- if (blocks.length != 16*16*(world.getMaxY() + 1)) {
- throw new InvalidFormatException("Chunk blocks byte array expected "
- + "to be " + 16*16*(world.getMaxY() + 1) + " bytes; found " + blocks.length);
- }
-
- if (data.length != 16*16*((world.getMaxY() + 1)/2)) {
- throw new InvalidFormatException("Chunk block data byte array "
- + "expected to be " + 16*16*((world.getMaxY() + 1)/2) + " bytes; found " + data.length);
- }
- }
+public interface Chunk {
/**
* Get the block ID of a block.
@@ -78,19 +12,8 @@ public class Chunk {
* @return
* @throws DataException
*/
- public int getBlockID(Vector pos) throws DataException {
- int x = pos.getBlockX() - rootX * 16;
- int y = pos.getBlockY();
- int z = pos.getBlockZ() - rootZ * 16;
- int index = y + (z * (world.getMaxY() + 1) + (x * (world.getMaxY() + 1) * 16));
-
- try {
- return blocks[index];
- } catch (IndexOutOfBoundsException e) {
- throw new DataException("Chunk does not contain position " + pos);
- }
- }
-
+ public int getBlockID(Vector pos) throws DataException;
+
/**
* Get the block data of a block.
*
@@ -98,90 +21,9 @@ public class Chunk {
* @return
* @throws DataException
*/
- public int getBlockData(Vector pos) throws DataException {
- int x = pos.getBlockX() - rootX * 16;
- int y = pos.getBlockY();
- int z = pos.getBlockZ() - rootZ * 16;
- int index = y + (z * (world.getMaxY() + 1) + (x * (world.getMaxY() + 1) * 16));
- boolean shift = index % 2 == 0;
- index /= 2;
-
- try {
- if (!shift) {
- return (data[index] & 0xF0) >> 4;
- } else {
- return data[index] & 0xF;
- }
- } catch (IndexOutOfBoundsException e) {
- throw new DataException("Chunk does not contain position " + pos);
- }
- }
-
- /**
- * Used to load the tile entities.
- *
- * @throws DataException
- */
- private void populateTileEntities() throws DataException {
- List tags = getChildTag(
- rootTag.getValue(), "TileEntities", ListTag.class)
- .getValue();
-
- tileEntities = new HashMap>();
-
- for (Tag tag : tags) {
- if (!(tag instanceof CompoundTag)) {
- throw new InvalidFormatException("CompoundTag expected in TileEntities");
- }
-
- CompoundTag t = (CompoundTag) tag;
-
- int x = 0;
- int y = 0;
- int z = 0;
-
- Map values = new HashMap();
-
- for (Map.Entry entry : t.getValue().entrySet()) {
- if (entry.getKey().equals("x")) {
- if (entry.getValue() instanceof IntTag) {
- x = ((IntTag) entry.getValue()).getValue();
- }
- } else if (entry.getKey().equals("y")) {
- if (entry.getValue() instanceof IntTag) {
- y = ((IntTag) entry.getValue()).getValue();
- }
- } else if (entry.getKey().equals("z")) {
- if (entry.getValue() instanceof IntTag) {
- z = ((IntTag) entry.getValue()).getValue();
- }
- }
-
- values.put(entry.getKey(), entry.getValue());
- }
-
- BlockVector vec = new BlockVector(x, y, z);
- tileEntities.put(vec, values);
- }
- }
-
- /**
- * Get the map of tags keyed to strings for a block's tile entity data. May
- * return null if there is no tile entity data. Not public yet because
- * what this function returns isn't ideal for usage.
- *
- * @param pos
- * @return
- * @throws DataException
- */
- private Map getBlockTileEntity(Vector pos) throws DataException {
- if (tileEntities == null) {
- populateTileEntities();
- }
-
- return tileEntities.get(new BlockVector(pos));
- }
-
+ public int getBlockData(Vector pos) throws DataException;
+
+
/**
* Get a block;
*
@@ -189,54 +31,5 @@ public class Chunk {
* @return block
* @throws DataException
*/
- public BaseBlock getBlock(Vector pos) throws DataException {
- int id = getBlockID(pos);
- int data = getBlockData(pos);
- BaseBlock block;
-
- if (id == BlockID.WALL_SIGN || id == BlockID.SIGN_POST) {
- block = new SignBlock(id, data);
- } else if (id == BlockID.CHEST) {
- block = new ChestBlock(data);
- } else if (id == BlockID.FURNACE || id == BlockID.BURNING_FURNACE) {
- block = new FurnaceBlock(id, data);
- } else if (id == BlockID.DISPENSER) {
- block = new DispenserBlock(data);
- } else if (id == BlockID.MOB_SPAWNER) {
- block = new MobSpawnerBlock(data);
- } else if (id == BlockID.NOTE_BLOCK) {
- block = new NoteBlock(data);
- } else {
- block = new BaseBlock(id, data);
- }
-
- if (block instanceof TileEntityBlock) {
- Map tileEntity = getBlockTileEntity(pos);
- ((TileEntityBlock) block).fromTileEntityNBT(tileEntity);
- }
-
- return block;
- }
-
- /**
- * Get child tag of a NBT structure.
- *
- * @param items
- * @param key
- * @param expected
- * @return child tag
- * @throws InvalidFormatException
- */
- @SuppressWarnings("unchecked")
- public static T getChildTag(Map items, String key,
- Class expected) throws InvalidFormatException {
- if (!items.containsKey(key)) {
- throw new InvalidFormatException("Missing a \"" + key + "\" tag");
- }
- Tag tag = items.get(key);
- if (!expected.isInstance(tag)) {
- throw new InvalidFormatException(key + " tag is not of tag type " + expected.getName());
- }
- return (T) tag;
- }
+ public BaseBlock getBlock(Vector pos) throws DataException;
}
diff --git a/src/main/java/com/sk89q/worldedit/data/ChunkStore.java b/src/main/java/com/sk89q/worldedit/data/ChunkStore.java
index 467bd5425..e4ca9e5f2 100644
--- a/src/main/java/com/sk89q/worldedit/data/ChunkStore.java
+++ b/src/main/java/com/sk89q/worldedit/data/ChunkStore.java
@@ -20,6 +20,8 @@
package com.sk89q.worldedit.data;
import java.io.IOException;
+import java.util.Map;
+
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.*;
@@ -64,7 +66,13 @@ public abstract class ChunkStore {
*/
public Chunk getChunk(Vector2D pos, LocalWorld world)
throws DataException, IOException {
- return new Chunk(world, getChunkTag(pos, world));
+
+ CompoundTag tag = getChunkTag(pos, world);
+ Map tags = tag.getValue();
+ if(tags.containsKey("Sections")) {
+ return new AnvilChunk(world, tag);
+ }
+ return new OldChunk(world, tag);
}
/**
diff --git a/src/main/java/com/sk89q/worldedit/data/FileMcRegionChunkStore.java b/src/main/java/com/sk89q/worldedit/data/FileMcRegionChunkStore.java
index f8e2ccde9..d1d645e97 100644
--- a/src/main/java/com/sk89q/worldedit/data/FileMcRegionChunkStore.java
+++ b/src/main/java/com/sk89q/worldedit/data/FileMcRegionChunkStore.java
@@ -45,7 +45,13 @@ public class FileMcRegionChunkStore extends McRegionChunkStore {
protected InputStream getInputStream(String name, String world) throws IOException,
DataException {
String fileName = "region" + File.separator + name;
- File file = new File(path, fileName);
+ File file = new File(path, fileName.replace("mcr", "mca")); // TODO: does this need a separate class?
+ if (!file.exists()) {
+ file = new File(path, fileName);
+ }
+ if (!file.exists()) {
+ file = new File(path, "DIM-1" + File.separator + fileName.replace("mcr", "mca")); // TODO: does this need a separate class?
+ }
if (!file.exists()) {
file = new File(path, "DIM-1" + File.separator + fileName);
}
diff --git a/src/main/java/com/sk89q/worldedit/data/OldChunk.java b/src/main/java/com/sk89q/worldedit/data/OldChunk.java
new file mode 100644
index 000000000..23ece3928
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/data/OldChunk.java
@@ -0,0 +1,205 @@
+// $Id$
+/*
+ * WorldEdit
+ * Copyright (C) 2010 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
+ * 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.data;
+
+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.*;
+
+/**
+ * Represents a chunk.
+ *
+ * @author sk89q
+ */
+public class OldChunk implements Chunk {
+ private CompoundTag rootTag;
+ private byte[] blocks;
+ private byte[] data;
+ private int rootX;
+ private int rootZ;
+
+ private Map> tileEntities;
+ @SuppressWarnings("unused")
+ private LocalWorld world; // TODO: remove if stays unused.
+
+ /**
+ * Construct the chunk with a compound tag.
+ *
+ * @param tag
+ * @throws DataException
+ */
+ public OldChunk(LocalWorld world, CompoundTag tag) throws DataException {
+ rootTag = tag;
+ this.world = world;
+
+
+ blocks = NBTUtils.getChildTag(rootTag.getValue(), "Blocks", ByteArrayTag.class).getValue();
+ data = NBTUtils.getChildTag( rootTag.getValue(), "Data", ByteArrayTag.class).getValue();
+ rootX = NBTUtils.getChildTag( rootTag.getValue(), "xPos", IntTag.class).getValue();
+ rootZ = NBTUtils.getChildTag( rootTag.getValue(), "zPos", IntTag.class).getValue();
+
+ int size = 16 * 16 * 128;
+ if (blocks.length != size) {
+ throw new InvalidFormatException("Chunk blocks byte array expected "
+ + "to be " + size + " bytes; found " + blocks.length);
+ }
+
+ if (data.length != (size/2)) {
+ throw new InvalidFormatException("Chunk block data byte array "
+ + "expected to be " + size + " bytes; found " + data.length);
+ }
+ }
+
+ @Override
+ public int getBlockID(Vector pos) throws DataException {
+ if(pos.getBlockY() >= 128) return 0;
+
+ int x = pos.getBlockX() - rootX * 16;
+ int y = pos.getBlockY();
+ int z = pos.getBlockZ() - rootZ * 16;
+ int index = y + (z * 128 + (x * 128 * 16));
+ try {
+ return blocks[index];
+ } catch (IndexOutOfBoundsException e) {
+ throw new DataException("Chunk does not contain position " + pos);
+ }
+ }
+
+ @Override
+ public int getBlockData(Vector pos) throws DataException {
+ if(pos.getBlockY() >= 128) return 0;
+
+ int x = pos.getBlockX() - rootX * 16;
+ int y = pos.getBlockY();
+ int z = pos.getBlockZ() - rootZ * 16;
+ int index = y + (z * 128 + (x * 128 * 16));
+ boolean shift = index % 2 == 0;
+ index /= 2;
+
+ try {
+ if (!shift) {
+ return (data[index] & 0xF0) >> 4;
+ } else {
+ return data[index] & 0xF;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new DataException("Chunk does not contain position " + pos);
+ }
+ }
+
+ /**
+ * Used to load the tile entities.
+ *
+ * @throws DataException
+ */
+ private void populateTileEntities() throws DataException {
+ List tags = NBTUtils.getChildTag(
+ rootTag.getValue(), "TileEntities", ListTag.class)
+ .getValue();
+
+ tileEntities = new HashMap>();
+
+ for (Tag tag : tags) {
+ if (!(tag instanceof CompoundTag)) {
+ throw new InvalidFormatException("CompoundTag expected in TileEntities");
+ }
+
+ CompoundTag t = (CompoundTag) tag;
+
+ int x = 0;
+ int y = 0;
+ int z = 0;
+
+ Map values = new HashMap();
+
+ for (Map.Entry entry : t.getValue().entrySet()) {
+ if (entry.getKey().equals("x")) {
+ if (entry.getValue() instanceof IntTag) {
+ x = ((IntTag) entry.getValue()).getValue();
+ }
+ } else if (entry.getKey().equals("y")) {
+ if (entry.getValue() instanceof IntTag) {
+ y = ((IntTag) entry.getValue()).getValue();
+ }
+ } else if (entry.getKey().equals("z")) {
+ if (entry.getValue() instanceof IntTag) {
+ z = ((IntTag) entry.getValue()).getValue();
+ }
+ }
+
+ values.put(entry.getKey(), entry.getValue());
+ }
+
+ BlockVector vec = new BlockVector(x, y, z);
+ tileEntities.put(vec, values);
+ }
+ }
+
+ /**
+ * Get the map of tags keyed to strings for a block's tile entity data. May
+ * return null if there is no tile entity data. Not public yet because
+ * what this function returns isn't ideal for usage.
+ *
+ * @param pos
+ * @return
+ * @throws DataException
+ */
+ private Map getBlockTileEntity(Vector pos) throws DataException {
+ if (tileEntities == null) {
+ populateTileEntities();
+ }
+
+ return tileEntities.get(new BlockVector(pos));
+ }
+
+ @Override
+ public BaseBlock getBlock(Vector pos) throws DataException {
+ int id = getBlockID(pos);
+ int data = getBlockData(pos);
+ BaseBlock block;
+
+ if (id == BlockID.WALL_SIGN || id == BlockID.SIGN_POST) {
+ block = new SignBlock(id, data);
+ } else if (id == BlockID.CHEST) {
+ block = new ChestBlock(data);
+ } else if (id == BlockID.FURNACE || id == BlockID.BURNING_FURNACE) {
+ block = new FurnaceBlock(id, data);
+ } else if (id == BlockID.DISPENSER) {
+ block = new DispenserBlock(data);
+ } else if (id == BlockID.MOB_SPAWNER) {
+ block = new MobSpawnerBlock(data);
+ } else if (id == BlockID.NOTE_BLOCK) {
+ block = new NoteBlock(data);
+ } else {
+ block = new BaseBlock(id, data);
+ }
+
+ if (block instanceof TileEntityBlock) {
+ Map tileEntity = getBlockTileEntity(pos);
+ ((TileEntityBlock) block).fromTileEntityNBT(tileEntity);
+ }
+
+ return block;
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/data/TrueZipMcRegionChunkStore.java b/src/main/java/com/sk89q/worldedit/data/TrueZipMcRegionChunkStore.java
index 9f8166f65..29c14774d 100644
--- a/src/main/java/com/sk89q/worldedit/data/TrueZipMcRegionChunkStore.java
+++ b/src/main/java/com/sk89q/worldedit/data/TrueZipMcRegionChunkStore.java
@@ -101,12 +101,20 @@ public class TrueZipMcRegionChunkStore extends McRegionChunkStore {
}
} else {
Pattern pattern = Pattern.compile(".*\\.mcr$");
+ Pattern patternmca = Pattern.compile(".*\\.mca$"); // TODO: does this need a separate class?
// World pattern
Pattern worldPattern = Pattern.compile(worldname + "\\$");
for (Enumeration extends ZipEntry> e = zip.entries(); e.hasMoreElements(); ) {
ZipEntry testEntry = (ZipEntry) e.nextElement();
// Check for world
if (worldPattern.matcher(worldname).matches()) {
+ // Check for file
+ // TODO: does this need a separate class?
+ if (patternmca.matcher(testEntry.getName()).matches()) {
+ folder = testEntry.getName().substring(0, testEntry.getName().lastIndexOf("/"));
+ name = folder + "/" + name.replace("mcr", "mca");
+ break;
+ }
// Check for file
if (pattern.matcher(testEntry.getName()).matches()) {
folder = testEntry.getName().substring(0, testEntry.getName().lastIndexOf("/"));
@@ -164,7 +172,7 @@ public class TrueZipMcRegionChunkStore extends McRegionChunkStore {
ZipEntry testEntry = e.nextElement();
- if (testEntry.getName().matches(".*\\.mcr$")) {
+ if (testEntry.getName().matches(".*\\.mcr$") || testEntry.getName().matches(".*\\.mca$")) { // TODO: does this need a separate class?
return true;
}
}
diff --git a/src/main/java/com/sk89q/worldedit/data/ZippedMcRegionChunkStore.java b/src/main/java/com/sk89q/worldedit/data/ZippedMcRegionChunkStore.java
index 473bceb74..f7f85a2ff 100644
--- a/src/main/java/com/sk89q/worldedit/data/ZippedMcRegionChunkStore.java
+++ b/src/main/java/com/sk89q/worldedit/data/ZippedMcRegionChunkStore.java
@@ -99,10 +99,17 @@ public class ZippedMcRegionChunkStore extends McRegionChunkStore {
}
} else {
Pattern pattern = Pattern.compile(".*\\.mcr$");
+ Pattern patternmca = Pattern.compile(".*\\.mca$"); // TODO: does this need a separate class?
for (Enumeration extends ZipEntry> e = zip.entries(); e.hasMoreElements(); ) {
ZipEntry testEntry = (ZipEntry) e.nextElement();
// Check for world
if (testEntry.getName().startsWith(worldname + "/")) {
+ // TODO: does this need a separate class?
+ if (patternmca.matcher(testEntry.getName()).matches()) {
+ folder = testEntry.getName().substring(0, testEntry.getName().lastIndexOf("/"));
+ name = folder + "/" + name.replace("mcr", "mca");
+ break;
+ }
if (pattern.matcher(testEntry.getName()).matches()) {
folder = testEntry.getName().substring(0, testEntry.getName().lastIndexOf("/"));
name = folder + "/" + name;
@@ -159,7 +166,7 @@ public class ZippedMcRegionChunkStore extends McRegionChunkStore {
ZipEntry testEntry = e.nextElement();
- if (testEntry.getName().matches(".*\\.mcr$")) {
+ if (testEntry.getName().matches(".*\\.mcr$") || testEntry.getName().matches(".*\\.mca$")) { // TODO: does this need a separate class?
return true;
}
}
diff --git a/src/main/java/com/sk89q/worldedit/snapshots/SnapshotRestore.java b/src/main/java/com/sk89q/worldedit/snapshots/SnapshotRestore.java
index 3c2058953..bcdd293e1 100644
--- a/src/main/java/com/sk89q/worldedit/snapshots/SnapshotRestore.java
+++ b/src/main/java/com/sk89q/worldedit/snapshots/SnapshotRestore.java
@@ -19,15 +19,25 @@
package com.sk89q.worldedit.snapshots;
-import com.sk89q.worldedit.*;
-import com.sk89q.worldedit.regions.*;
-import com.sk89q.worldedit.blocks.*;
-import com.sk89q.worldedit.data.*;
import java.io.IOException;
-import java.util.Map;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
-import java.util.ArrayList;
+import java.util.Map;
+
+import com.sk89q.worldedit.BlockVector2D;
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.MaxChangedBlocksException;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.Vector2D;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.data.Chunk;
+import com.sk89q.worldedit.data.ChunkStore;
+import com.sk89q.worldedit.data.DataException;
+import com.sk89q.worldedit.data.MissingChunkException;
+import com.sk89q.worldedit.data.MissingWorldException;
+import com.sk89q.worldedit.regions.CuboidRegion;
+import com.sk89q.worldedit.regions.Region;
/**
*