diff --git a/src/main/java/com/sk89q/worldedit/foundation/Block.java b/src/main/java/com/sk89q/worldedit/foundation/Block.java
new file mode 100644
index 000000000..3f77873d1
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/foundation/Block.java
@@ -0,0 +1,226 @@
+// $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.foundation;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.blocks.TileEntityBlock;
+import com.sk89q.worldedit.data.DataException;
+
+/**
+ * Represents a mutable copy of a block that is not tied to any 'real' block in a world.
+ * A single instance of this can be set to multiple locations and each location would
+ * have a copy of this instance's data.
+ *
+ * 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
+ * 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
+ * structures if possible.
+ *
+ * Currently, {@link BaseBlock} is used throughout WorldEdit and implementations, but
+ * eventually an API-breaking transition will occur to switch to this object instead.
+ * As-is, the definition of this class is complete, but may need changes in MC 1.4
+ * because data values may be eradicated.
+ */
+public class Block implements TileEntityBlock {
+
+ /**
+ * Indicates the highest possible block ID (inclusive) that can be used. This value
+ * is subject to change depending on the implementation, but internally this class
+ * only supports a range of 4096 IDs (for space reasons), which coincides with the
+ * number of possible IDs that official Minecraft supports as of version 1.3.
+ */
+ public static final int MAX_ID = 4095;
+
+ /**
+ * Indicates the maximum data value (inclusive) that can be used. Minecraft 1.4 may
+ * abolish usage of data values and this value may be removed in the future.
+ */
+ public static final int MAX_DATA = 15;
+
+ // Instances of this class should be _as small as possible_ because there will
+ // be millions of instances of this object.
+
+ private short rawIdData;
+ private CompoundTag nbtData;
+
+ /**
+ * Construct a block with the given ID and a data value of 0.
+ *
+ * @param id ID value
+ * @see #setId(int)
+ */
+ public Block(int id) {
+ setId(id);
+ setData(0);
+ }
+
+ /**
+ * Construct a block with the given ID and data value.
+ *
+ * @param id ID value
+ * @param data data value
+ * @see #setId(int)
+ * @see #setData(int)
+ */
+ public Block(int id, int data) {
+ setId(id);
+ setData(data);
+ }
+
+ /**
+ * Construct a block with the given ID, data value, and NBT data structure.
+ *
+ * @param id ID value
+ * @param data data value
+ * @param nbtData NBT data
+ * @throws DataException if possibly the data is invalid
+ * @see #setId(int)
+ * @see #setData(int)
+ * @see #setNbtData(CompoundTag)
+ */
+ public Block(int id, int data, CompoundTag nbtData) throws DataException {
+ setId(id);
+ setData(data);
+ setNbtData(nbtData);
+ }
+
+ /**
+ * Get the ID of the block.
+ *
+ * @return ID (between 0 and {@link #MAX_ID})
+ */
+ public int getId() {
+ return rawIdData >> 4;
+ }
+
+ /**
+ * Set the block ID.
+ *
+ * @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 < 0) {
+ throw new IllegalArgumentException("Can't have a block ID below 0");
+ }
+
+ rawIdData = (short) ((id << 4) | rawIdData & 0xf);
+ }
+
+ /**
+ * Get the block's data value.
+ *
+ * @return data value (0-15)
+ */
+ public int getData() {
+ return rawIdData & 0xf;
+ }
+
+ /**
+ * Set the block's data value.
+ *
+ * @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 < 0) {
+ throw new IllegalArgumentException("Can't have a block data value below 0");
+ }
+
+ rawIdData = (short) ((rawIdData ^ 4) | data);
+ }
+
+ /**
+ * Set both the block's ID and data value.
+ *
+ * @param id ID value
+ * @param data data value
+ * @see #setId(int)
+ * @see #setData(int)
+ */
+ public void setIdAndData(int id, int data) {
+ setId(id);
+ setData(data);
+ }
+
+ /**
+ * Returns whether the block contains NBT data.
+ *
+ * @return NBT data;
+ */
+ 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();
+ if (nbtData == null) {
+ return "";
+ }
+ Tag idTag = nbtData.getValue().get("id");
+ if (idTag != null && idTag instanceof StringTag) {
+ return ((StringTag) idTag).getValue();
+ } else {
+ return "";
+ }
+ }
+
+ @Override
+ public CompoundTag getNbtData() {
+ return nbtData;
+ }
+
+ @Override
+ public void setNbtData(CompoundTag nbtData) throws DataException {
+ this.nbtData = nbtData;
+ }
+
+ @Override
+ public int hashCode() {
+ int ret = getId() << 3;
+ if (getData() != (byte) -1) ret |= getData();
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return "Block{ID:" + getId() + ", Data: " + getData() + "}";
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/foundation/NbtValued.java b/src/main/java/com/sk89q/worldedit/foundation/NbtValued.java
new file mode 100644
index 000000000..8236fdc0f
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/foundation/NbtValued.java
@@ -0,0 +1,49 @@
+// $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.foundation;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.worldedit.data.DataException;
+
+/**
+ * Indicates an object that contains extra data identified as an NBT structure. This
+ * interface is used when saving and loading objects to a serialized format, but may
+ * be used in other cases.
+ */
+public interface NbtValued {
+
+ /**
+ * 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.
+ *
+ * @return compound tag, or null
+ */
+ CompoundTag getNbtData();
+
+ /**
+ * Set the object's NBT data (tile entity data).
+ *
+ * @param nbtData NBT data, or null if no data
+ * @throws DataException if possibly the data is invalid
+ */
+ void setNbtData(CompoundTag nbtData) throws DataException;
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/foundation/World.java b/src/main/java/com/sk89q/worldedit/foundation/World.java
new file mode 100644
index 000000000..d01a0abad
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/foundation/World.java
@@ -0,0 +1,69 @@
+// $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.foundation;
+
+import com.sk89q.worldedit.LocalWorld;
+import com.sk89q.worldedit.Vector;
+
+/**
+ * Represents a world instance that can be modified. The world instance could be
+ * loaded in-game or loaded in a stand-alone editor.
+ *
+ * This class is meant to replace {@link LocalWorld} eventually, once this class has been
+ * fleshed out with the required methods and it has been decided that it is time to
+ * start breaking some API compatibility.
+ */
+public interface World {
+
+ /**
+ * Change the block at the given location to the given block. The operation may
+ * not tie the given {@link Block} to the world, so future changes to the
+ * {@link Block} do not affect the world until this method is called again.
+ *
+ * Implementations may or may not consider the value of the notifyAdjacent
+ * parameter, and implementations may to choose to either apply physics anyway or
+ * to not apply any physics (particularly in a stand-alone implementation).
+ *
+ * The return value of this method indicates whether the change "went through," as
+ * in the block was changed in the world in any way. If the new block is no different
+ * than the block already at the position in the world, 'false' would be returned.
+ * If the position is invalid (out of bounds, for example), then nothing should
+ * occur and 'false' should be returned. If possible, the return value should be
+ * accurate as possible, but implementations may choose to not provide an accurate
+ * value if it is not possible to know.
+ *
+ * @param location location of the block
+ * @param block block to set
+ * @param notifyAdjacent true to to notify adjacent (perform physics)
+ * @return true if the block was successfully set (return value may not be accurate)
+ */
+ boolean setBlock(Vector location, Block block, boolean notifyAdjacent);
+
+ /**
+ * Get a copy of the block at the given location. May return null if the location
+ * given is out of bounds. The returned block must not be tied to any real block
+ * in the world, so changes to the returned {@link Block} have no effect until
+ * {@link #setBlock(Vector, Block, boolean)} is called.
+ *
+ * @param location location of the block
+ * @return the block, or null if the block does not exist
+ */
+ Block getBlock(Vector location);
+
+}