Updated foundation classes a bit and added raw access for NBT. This release marks experimental support for custom blocks, and nearly all future Minecraft blocks, and is also the beginning of the gradual transition to the new foundation classes as a replacement of the current BaseBlock, etc. classes.

Dieser Commit ist enthalten in:
sk89q 2012-08-23 16:52:37 -07:00
Ursprung a2aae2c4da
Commit 48af65cac3
21 geänderte Dateien mit 1037 neuen und 515 gelöschten Zeilen

Datei anzeigen

@ -63,4 +63,40 @@ public final class 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);
}
}
} }

Datei anzeigen

@ -18,27 +18,35 @@
*/ */
package com.sk89q.worldedit; 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.ArrayList;
import java.util.Collections; 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 java.util.Random;
import com.sk89q.worldedit.regions.*; import java.util.Set;
import com.sk89q.worldedit.util.TreeGenerator; import java.util.Stack;
import com.sk89q.worldedit.bags.*;
import com.sk89q.worldedit.blocks.*; 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.Expression;
import com.sk89q.worldedit.expression.ExpressionException; import com.sk89q.worldedit.expression.ExpressionException;
import com.sk89q.worldedit.expression.runtime.RValue; import com.sk89q.worldedit.expression.runtime.RValue;
import com.sk89q.worldedit.masks.Mask; 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 * This class can wrap all block editing operations into one "edit session" that
@ -408,53 +416,7 @@ public class EditSession {
* @return BaseBlock * @return BaseBlock
*/ */
public BaseBlock rawGetBlock(Vector pt) { public BaseBlock rawGetBlock(Vector pt) {
world.checkLoadedChunk(pt); return world.getBlock(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);
}
} }
/** /**
@ -464,8 +426,8 @@ public class EditSession {
*/ */
public void undo(EditSession sess) { public void undo(EditSession sess) {
for (Map.Entry<BlockVector, BaseBlock> entry : original) { for (Map.Entry<BlockVector, BaseBlock> entry : original) {
BlockVector pt = (BlockVector) entry.getKey(); BlockVector pt = entry.getKey();
sess.smartSetBlock(pt, (BaseBlock) entry.getValue()); sess.smartSetBlock(pt, entry.getValue());
} }
sess.flushQueue(); sess.flushQueue();
} }
@ -477,8 +439,8 @@ public class EditSession {
*/ */
public void redo(EditSession sess) { public void redo(EditSession sess) {
for (Map.Entry<BlockVector, BaseBlock> entry : current) { for (Map.Entry<BlockVector, BaseBlock> entry : current) {
BlockVector pt = (BlockVector) entry.getKey(); BlockVector pt = entry.getKey();
sess.smartSetBlock(pt, (BaseBlock) entry.getValue()); sess.smartSetBlock(pt, entry.getValue());
} }
sess.flushQueue(); sess.flushQueue();
} }
@ -727,8 +689,8 @@ public class EditSession {
final Set<BlockVector2D> dirtyChunks = new HashSet<BlockVector2D>(); final Set<BlockVector2D> dirtyChunks = new HashSet<BlockVector2D>();
for (Map.Entry<BlockVector, BaseBlock> entry : queueAfter) { for (Map.Entry<BlockVector, BaseBlock> entry : queueAfter) {
BlockVector pt = (BlockVector) entry.getKey(); BlockVector pt = entry.getKey();
rawSetBlock(pt, (BaseBlock) entry.getValue()); rawSetBlock(pt, entry.getValue());
// TODO: use ChunkStore.toChunk(pt) after optimizing it. // TODO: use ChunkStore.toChunk(pt) after optimizing it.
if (fastMode) { if (fastMode) {
@ -740,8 +702,8 @@ public class EditSession {
// because it might cause the items to drop // because it might cause the items to drop
if (blockBag == null || missingBlocks.size() == 0) { if (blockBag == null || missingBlocks.size() == 0) {
for (Map.Entry<BlockVector, BaseBlock> entry : queueLast) { for (Map.Entry<BlockVector, BaseBlock> entry : queueLast) {
BlockVector pt = (BlockVector) entry.getKey(); BlockVector pt = entry.getKey();
rawSetBlock(pt, (BaseBlock) entry.getValue()); rawSetBlock(pt, entry.getValue());
// TODO: use ChunkStore.toChunk(pt) after optimizing it. // TODO: use ChunkStore.toChunk(pt) after optimizing it.
if (fastMode) { if (fastMode) {

Datei anzeigen

@ -21,9 +21,19 @@ package com.sk89q.worldedit;
import java.util.PriorityQueue; import java.util.PriorityQueue;
import java.util.Random; import java.util.Random;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType; 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.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
@ -32,7 +42,7 @@ import com.sk89q.worldedit.util.TreeGenerator;
* *
* @author sk89q * @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)} * Named flags to use as parameters to {@link LocalWorld#killMobs(Vector, double, int)}
*/ */
@ -64,6 +74,7 @@ public abstract class LocalWorld {
* @param type * @param type
* @return * @return
*/ */
@Deprecated
public abstract boolean setBlockType(Vector pt, int type); public abstract boolean setBlockType(Vector pt, int type);
/** /**
@ -73,6 +84,7 @@ public abstract class LocalWorld {
* @param type * @param type
* @return * @return
*/ */
@Deprecated
public boolean setBlockTypeFast(Vector pt, int type) { public boolean setBlockTypeFast(Vector pt, int type) {
return setBlockType(pt, type); return setBlockType(pt, type);
} }
@ -83,6 +95,7 @@ public abstract class LocalWorld {
* @param pt * @param pt
* @return * @return
*/ */
@Deprecated
public abstract int getBlockType(Vector pt); public abstract int getBlockType(Vector pt);
/** /**
@ -91,7 +104,7 @@ public abstract class LocalWorld {
* @param pt * @param pt
* @param data * @param data
*/ */
@Deprecated
public abstract void setBlockData(Vector pt, int data); public abstract void setBlockData(Vector pt, int data);
/** /**
@ -100,6 +113,7 @@ public abstract class LocalWorld {
* @param pt * @param pt
* @param data * @param data
*/ */
@Deprecated
public abstract void setBlockDataFast(Vector pt, int data); public abstract void setBlockDataFast(Vector pt, int data);
/** /**
@ -124,6 +138,7 @@ public abstract class LocalWorld {
* @param data * @param data
* @return * @return
*/ */
@Deprecated
public boolean setTypeIdAndData(Vector pt, int type, int data) { public boolean setTypeIdAndData(Vector pt, int type, int data) {
boolean ret = setBlockType(pt, type); boolean ret = setBlockType(pt, type);
setBlockData(pt, data); setBlockData(pt, data);
@ -137,6 +152,7 @@ public abstract class LocalWorld {
* @param data * @param data
* @return * @return
*/ */
@Deprecated
public boolean setTypeIdAndDataFast(Vector pt, int type, int data) { public boolean setTypeIdAndDataFast(Vector pt, int type, int data) {
boolean ret = setBlockTypeFast(pt, type); boolean ret = setBlockTypeFast(pt, type);
setBlockDataFast(pt, data); setBlockDataFast(pt, data);
@ -149,6 +165,7 @@ public abstract class LocalWorld {
* @param pt * @param pt
* @return * @return
*/ */
@Deprecated
public abstract int getBlockData(Vector pt); 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) { public boolean queueBlockBreakEffect(ServerInterface server, Vector position, int blockId, double priority) {
if (taskId == -1) { if (taskId == -1) {
taskId = server.schedule(0, 1, new Runnable() { taskId = server.schedule(0, 1, new Runnable() {
@Override
public void run() { public void run() {
int max = Math.max(1, Math.min(30, effectQueue.size() / 3)); int max = Math.max(1, Math.min(30, effectQueue.size() / 3));
for (int i = 0; i < max; ++i) { for (int i = 0; i < max; ++i) {
@ -509,4 +527,73 @@ public abstract class LocalWorld {
public int killEntities(LocalEntity... entities) { public int killEntities(LocalEntity... entities) {
return 0; 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);
}
}
} }

Datei anzeigen

@ -20,26 +20,20 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection; import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.foundation.Block;
/** /**
* Represents a block. * Represents a block.
* *
* @see Block new class to replace this one
* @author sk89q * @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) { public BaseBlock(int type) {
this(type, 0); this(type, 0);
@ -48,40 +42,29 @@ public class BaseBlock {
/** /**
* Construct the block with its type and data. * Construct the block with its type and data.
* *
* @param type * @param type type ID of block
* @param data * @param data data value
*/ */
public BaseBlock(int type, int data) { public BaseBlock(int type, int data) {
this.type = (short) type; super(type, data);
this.data = (short) data;
} }
/** /**
* Get the type of block.
*
* @return the type * @return the type
*/ */
public int getType() { public int getType() {
return (int) type; return getId();
} }
/** /**
* Set the type of block.
*
* @param type the type to set * @param type the type to set
*/ */
public void setType(int type) { public void setType(int type) {
this.type = (short) type; setId(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;
} }
/** /**
@ -90,24 +73,28 @@ public class BaseBlock {
* @return if air * @return if air
*/ */
public boolean isAir() { public boolean isAir() {
return type == BlockID.AIR; return getType() == BlockID.AIR;
} }
/** /**
* Rotate this block 90 degrees. * Rotate this block 90 degrees.
*
* @return new data value
*/ */
public int rotate90() { public int rotate90() {
int newData = BlockData.rotate90(type, data); int newData = BlockData.rotate90(getType(), getData());
this.data = (short) newData; setData(newData);
return data; return newData;
} }
/** /**
* Rotate this block -90 degrees. * Rotate this block -90 degrees.
*
* @return new data value
*/ */
public int rotate90Reverse() { public int rotate90Reverse() {
int newData = BlockData.rotate90Reverse(type, data); int newData = BlockData.rotate90Reverse(getType(), getData());
this.data = (short) newData; setData((short) newData);
return newData; return newData;
} }
@ -118,56 +105,55 @@ public class BaseBlock {
* @return new data value * @return new data value
*/ */
public int cycleData(int increment) { public int cycleData(int increment) {
int newData = BlockData.cycle(this.type, this.data, increment); int newData = BlockData.cycle(getType(), getData(), increment);
this.data = (short) newData; setData((short) newData);
return newData; return newData;
} }
/** /**
* Flip this block. * Flip this block.
*
* @return this block
*/ */
public BaseBlock flip() { public BaseBlock flip() {
data = (short) BlockData.flip(type, data); setData((short) BlockData.flip(getType(), getData()));
return this; return this;
} }
/** /**
* Flip this block. * Flip this block.
* @param direction *
* @param direction direction to flip in
* @return this block
*/ */
public BaseBlock flip(FlipDirection direction) { public BaseBlock flip(FlipDirection direction) {
data = (short) BlockData.flip(type, data, direction); setData((short) BlockData.flip(getType(), getData(), direction));
return this; return this;
} }
/**
* Checks whether the type ID and data value are equal.
*/
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof BaseBlock)) { if (!(o instanceof BaseBlock)) {
return false; return false;
} }
return type == ((BaseBlock) o).type && data == ((BaseBlock) o).data; return getType() == ((BaseBlock) o).getType() && getData() == ((BaseBlock) o).getData();
}
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();
} }
/** /**
* 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 * @param iter
* @return * @return
* @deprecated This method is silly * @deprecated This method is silly

Datei anzeigen

@ -23,44 +23,41 @@ import java.util.HashMap;
import java.util.Map; 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 * @author sk89q
*/ */
public class BaseItem { public class BaseItem {
/**
* Item ID.
*/
private int id;
/**
* Item damage.
*/
private short damage;
private Map<Integer, Integer> enchantments = new HashMap<Integer, Integer>(); private int id;
private short data;
private final Map<Integer, Integer> enchantments = new HashMap<Integer, Integer>();
/** /**
* Construct the object. * Construct the object.
* *
* @param id * @param id ID of the item
*/ */
public BaseItem(int id) { public BaseItem(int id) {
this.id = id; this.id = id;
this.damage = 0; this.data = 0;
} }
/** /**
* Construct the object. * Construct the object.
* *
* @param id * @param id ID of the item
* @param damage * @param data data value of the item
*/ */
public BaseItem(int id, short damage) { public BaseItem(int id, short data) {
this.id = id; this.id = id;
this.damage = damage; this.data = data;
} }
/** /**
* Get the type of item.
*
* @return the id * @return the id
*/ */
public int getType() { public int getType() {
@ -68,6 +65,8 @@ public class BaseItem {
} }
/** /**
* Get the type of item.
*
* @param id the id to set * @param id the id to set
*/ */
public void setType(int id) { public void setType(int id) {
@ -75,19 +74,48 @@ public class BaseItem {
} }
/** /**
* Get the damage value.
*
* @return the damage * @return the damage
*/ */
@Deprecated
public short getDamage() { 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) { public short getData() {
this.damage = damage; 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<Integer, Integer> getEnchantments() { public Map<Integer, Integer> getEnchantments() {
return enchantments; return enchantments;
} }

Datei anzeigen

@ -31,9 +31,9 @@ public class BaseItemStack extends BaseItem {
private int amount = 1; 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) { public BaseItemStack(int id) {
super(id); super(id);
@ -42,8 +42,8 @@ public class BaseItemStack extends BaseItem {
/** /**
* Construct the object. * Construct the object.
* *
* @param id * @param id type ID
* @param amount * @param amount amount in the stack
*/ */
public BaseItemStack(int id, int amount) { public BaseItemStack(int id, int amount) {
super(id); super(id);
@ -53,16 +53,18 @@ public class BaseItemStack extends BaseItem {
/** /**
* Construct the object. * Construct the object.
* *
* @param id * @param id type ID
* @param amount * @param amount amount in the stack
* @param damage * @param data data value
*/ */
public BaseItemStack(int id, int amount, short damage) { public BaseItemStack(int id, int amount, short data) {
super(id, damage); super(id, data);
this.amount = amount; this.amount = amount;
} }
/** /**
* Get the number of items in the stack.
*
* @return the amount * @return the amount
*/ */
public int getAmount() { 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 * @param amount the amount to set
*/ */
public void setAmount(int amount) { public void setAmount(int amount) {

Datei anzeigen

@ -19,87 +19,79 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import com.sk89q.jnbt.*; import java.util.ArrayList;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; 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 * @author sk89q
*/ */
public class ChestBlock extends ContainerBlock { public class ChestBlock extends ContainerBlock {
/** /**
* Construct the chest block. * Construct an empty chest block with the default orientation (data value).
*/ */
public ChestBlock() { public ChestBlock() {
super(BlockID.CHEST, 27); 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) { public ChestBlock(int data) {
super(BlockID.CHEST, data, 27); 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 data data indicating the position of the chest
* @param items * @param items array of items
*/ */
public ChestBlock(int data, BaseItemStack[] items) { public ChestBlock(int data, BaseItemStack[] items) {
super(BlockID.CHEST, data, 27); super(BlockID.CHEST, data, 27);
setItems(items); setItems(items);
} }
/** @Override
* Get the tile entity ID. public String getNbtId() {
*
* @return
*/
public String getTileEntityID() {
return "Chest"; return "Chest";
} }
/** @Override
* Store additional tile entity data. Returns true if the data is used. public CompoundTag getNbtData() {
*
* @return map of values
* @throws DataException
*/
public Map<String, Tag> toTileEntityNBT()
throws DataException {
Map<String, Tag> values = new HashMap<String, Tag>(); Map<String, Tag> values = new HashMap<String, Tag>();
values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(getItems()))); values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(getItems())));
return values; return new CompoundTag(getNbtId(), values);
} }
/** @Override
* Get additional information from the title entity data. public void setNbtData(CompoundTag rootTag) throws DataException {
* if (rootTag == null) {
* @param values
* @throws DataException
*/
public void fromTileEntityNBT(Map<String, Tag> values)
throws DataException {
if (values == null) {
return; return;
} }
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id"); Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Chest")) { if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Chest")) {
throw new DataException("'Chest' tile entity expected"); throw new DataException("'Chest' tile entity expected");
} }
List<CompoundTag> items = new ArrayList<CompoundTag>(); List<CompoundTag> items = new ArrayList<CompoundTag>();
for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) { for (Tag tag : NBTUtils.getChildTag(values, "Items", ListTag.class).getValue()) {
if (!(tag instanceof CompoundTag)) { if (!(tag instanceof CompoundTag)) {
throw new DataException("CompoundTag expected as child tag of Chest's Items"); throw new DataException("CompoundTag expected as child tag of Chest's Items");

Datei anzeigen

@ -19,6 +19,11 @@
package com.sk89q.worldedit.blocks; 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.ByteTag;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
@ -27,17 +32,13 @@ import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.data.DataException; 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. * Represents a block that stores items.
* *
* @author sk89q * @author sk89q
*/ */
public abstract class ContainerBlock extends BaseBlock implements TileEntityBlock { public abstract class ContainerBlock extends BaseBlock implements TileEntityBlock {
private BaseItemStack[] items; private BaseItemStack[] items;
public ContainerBlock(int type, int inventorySize) { public ContainerBlock(int type, int inventorySize) {
@ -50,7 +51,6 @@ public abstract class ContainerBlock extends BaseBlock implements TileEntityBloc
this.items = new BaseItemStack[inventorySize]; this.items = new BaseItemStack[inventorySize];
} }
/** /**
* Get the list of items. * Get the list of items.
* *
@ -69,6 +69,11 @@ public abstract class ContainerBlock extends BaseBlock implements TileEntityBloc
this.items = items; this.items = items;
} }
@Override
public boolean hasNbtData() {
return true;
}
public Map<String, Tag> serializeItem(BaseItemStack item) { public Map<String, Tag> serializeItem(BaseItemStack item) {
Map<String, Tag> data = new HashMap<String, Tag>(); Map<String, Tag> data = new HashMap<String, Tag>();
data.put("id", new ShortTag("id", (short) item.getType())); data.put("id", new ShortTag("id", (short) item.getType()));

Datei anzeigen

@ -19,12 +19,17 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import com.sk89q.jnbt.*; import java.util.ArrayList;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; 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. * Represents dispensers.
@ -34,66 +39,53 @@ import java.util.ArrayList;
public class DispenserBlock extends ContainerBlock { public class DispenserBlock extends ContainerBlock {
/** /**
* Construct the dispenser block. * Construct an empty dispenser block.
*/ */
public DispenserBlock() { public DispenserBlock() {
super(BlockID.DISPENSER, 9); super(BlockID.DISPENSER, 9);
} }
/** /**
* Construct the dispenser block. * Construct an empty dispenser block.
* *
* @param data * @param data data value (orientation)
*/ */
public DispenserBlock(int data) { public DispenserBlock(int data) {
super(BlockID.DISPENSER, data, 9); super(BlockID.DISPENSER, data, 9);
} }
/** /**
* Construct the dispenser block. * Construct a dispenser block with the given orientation and inventory.
* *
* @param data * @param data data value (orientation)
* @param items * @param items array of items in the inventory
*/ */
public DispenserBlock(int data, BaseItemStack[] items) { public DispenserBlock(int data, BaseItemStack[] items) {
super(BlockID.DISPENSER, data, 9); super(BlockID.DISPENSER, data, 9);
this.setItems(items); this.setItems(items);
} }
/** @Override
* Get the tile entity ID. public String getNbtId() {
*
* @return
*/
public String getTileEntityID() {
return "Trap"; return "Trap";
} }
/** @Override
* Store additional tile entity data. Returns true if the data is used. public CompoundTag getNbtData() {
*
* @return map of values
* @throws DataException
*/
public Map<String, Tag> toTileEntityNBT()
throws DataException {
Map<String, Tag> values = new HashMap<String, Tag>(); Map<String, Tag> values = new HashMap<String, Tag>();
values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(getItems()))); values.put("Items", new ListTag("Items", CompoundTag.class,
return values; serializeInventory(getItems())));
return new CompoundTag(getNbtId(), values);
} }
/** @Override
* Get additional information from the title entity data. public void setNbtData(CompoundTag rootTag) throws DataException {
* if (rootTag == null) {
* @param values
* @throws DataException
*/
public void fromTileEntityNBT(Map<String, Tag> values)
throws DataException {
if (values == null) {
return; return;
} }
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id"); Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Trap")) { if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("Trap")) {
throw new DataException("'Trap' tile entity expected"); throw new DataException("'Trap' tile entity expected");

Datei anzeigen

@ -15,60 +15,58 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.data.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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 * @author sk89q
*/ */
public class FurnaceBlock extends ContainerBlock { public class FurnaceBlock extends ContainerBlock {
/**
* Fuel time.
*/
private short burnTime; private short burnTime;
/**
* Cook time.
*/
private short cookTime; private short cookTime;
/** /**
* Construct the chest block. * Construct an empty furnace block with the default orientation.
* *
* @param type * @param type type ID
*/ */
public FurnaceBlock(int type) { public FurnaceBlock(int type) {
super(type, 2); super(type, 2);
} }
/** /**
* Construct the chest block. * Construct an empty furnace block with a given orientation.
* *
* @param type * @param type type ID
* @param data * @param data orientation
*/ */
public FurnaceBlock(int type, int data) { public FurnaceBlock(int type, int data) {
super(type, data, 2); super(type, data, 2);
} }
/** /**
* Construct the chest block. * Construct an furnace block with a given orientation and inventory.
* *
* @param type * @param type type ID
* @param data * @param data orientation
* @param items * @param items inventory items
*/ */
public FurnaceBlock(int type, int data, BaseItemStack[] items) { public FurnaceBlock(int type, int data, BaseItemStack[] items) {
super(type, data, 2); 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() { public short getBurnTime() {
return burnTime; return burnTime;
} }
/** /**
* @param burnTime the burnTime to set * Set the burn time.
*
* @param burnTime the burn time
*/ */
public void setBurnTime(short burnTime) { public void setBurnTime(short burnTime) {
this.burnTime = burnTime; this.burnTime = burnTime;
} }
/** /**
* @return the cookTime * Get the cook time.
*
* @return the cook time
*/ */
public short getCookTime() { public short getCookTime() {
return cookTime; return cookTime;
} }
/** /**
* @param cookTime the cookTime to set * Set the cook time.
*
* @param cookTime the cook time to set
*/ */
public void setCookTime(short cookTime) { public void setCookTime(short cookTime) {
this.cookTime = cookTime; this.cookTime = cookTime;
} }
/** @Override
* Get the tile entity ID. public String getNbtId() {
*
* @return
*/
public String getTileEntityID() {
return "Furnace"; return "Furnace";
} }
/** @Override
* Store additional tile entity data. Returns true if the data is used. public CompoundTag getNbtData() {
*
* @return map of values
* @throws DataException
*/
public Map<String, Tag> toTileEntityNBT()
throws DataException {
Map<String, Tag> values = new HashMap<String, Tag>(); Map<String, Tag> values = new HashMap<String, Tag>();
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("BurnTime", new ShortTag("BurnTime", burnTime));
values.put("CookTime", new ShortTag("CookTime", cookTime)); values.put("CookTime", new ShortTag("CookTime", cookTime));
return values; return new CompoundTag(getNbtId(), values);
} }
/** @Override
* Get additional information from the title entity data. public void setNbtData(CompoundTag rootTag) throws DataException {
* if (rootTag == null) {
* @param values
* @throws DataException
*/
public void fromTileEntityNBT(Map<String, Tag> values)
throws DataException {
if (values == null) {
return; return;
} }
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id"); 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"); throw new DataException("'Furnace' tile entity expected");
} }
@ -150,7 +144,8 @@ public class FurnaceBlock extends ContainerBlock {
for (Tag tag : items.getValue()) { for (Tag tag : items.getValue()) {
if (!(tag instanceof CompoundTag)) { 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); compound.add((CompoundTag) tag);
} }

Datei anzeigen

@ -19,30 +19,29 @@
package com.sk89q.worldedit.blocks; 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.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 * @author sk89q
*/ */
public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock { public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
/**
* Store mob spawn type.
*/
private String mobType; private String mobType;
/**
* Delay until next spawn.
*/
private short delay; private short delay;
/** /**
* Construct the mob spawner block. * Construct the mob spawner block with a pig as the mob type.
*
*/ */
public MobSpawnerBlock() { public MobSpawnerBlock() {
super(BlockID.MOB_SPAWNER); 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) { public MobSpawnerBlock(String mobType) {
super(BlockID.MOB_SPAWNER); 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) { public MobSpawnerBlock(int data) {
super(BlockID.MOB_SPAWNER, data); super(BlockID.MOB_SPAWNER, data);
@ -71,8 +70,8 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
/** /**
* Construct the mob spawner block. * Construct the mob spawner block.
* *
* @param data * @param data data value
* @param mobType * @param mobType mob type
*/ */
public MobSpawnerBlock(int data, String mobType) { public MobSpawnerBlock(int data, String mobType) {
super(BlockID.MOB_SPAWNER, data); super(BlockID.MOB_SPAWNER, data);
@ -82,7 +81,7 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
/** /**
* Get the mob type. * Get the mob type.
* *
* @return * @return the mob type
*/ */
public String getMobType() { public String getMobType() {
return mobType; return mobType;
@ -91,13 +90,15 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
/** /**
* Set the mob type. * Set the mob type.
* *
* @param mobType * @param mobType the mob type
*/ */
public void setMobType(String mobType) { public void setMobType(String mobType) {
this.mobType = mobType; this.mobType = mobType;
} }
/** /**
* Get the spawn delay.
*
* @return the delay * @return the delay
*/ */
public short getDelay() { public short getDelay() {
@ -105,47 +106,40 @@ public class MobSpawnerBlock extends BaseBlock implements TileEntityBlock {
} }
/** /**
* Set the spawn delay.
*
* @param delay the delay to set * @param delay the delay to set
*/ */
public void setDelay(short delay) { public void setDelay(short delay) {
this.delay = delay; this.delay = delay;
} }
/** @Override
* Get the tile entity ID. public boolean hasNbtData() {
* return true;
* @return }
*/
public String getTileEntityID() { @Override
public String getNbtId() {
return "MobSpawner"; return "MobSpawner";
} }
/** @Override
* Store additional tile entity data. Returns true if the data is used. public CompoundTag getNbtData() {
*
* @return map of values
* @throws DataException
*/
public Map<String, Tag> toTileEntityNBT()
throws DataException {
Map<String, Tag> values = new HashMap<String, Tag>(); Map<String, Tag> values = new HashMap<String, Tag>();
values.put("EntityId", new StringTag("EntityId", mobType)); values.put("EntityId", new StringTag("EntityId", mobType));
values.put("Delay", new ShortTag("Delay", delay)); values.put("Delay", new ShortTag("Delay", delay));
return values; return new CompoundTag(getNbtId(), values);
} }
/** @Override
* Get additional information from the title entity data. public void setNbtData(CompoundTag rootTag) throws DataException {
* if (rootTag == null) {
* @param values
* @throws DataException
*/
public void fromTileEntityNBT(Map<String, Tag> values)
throws DataException {
if (values == null) {
return; return;
} }
Map<String, Tag> values = rootTag.getValue();
Tag t = values.get("id"); Tag t = values.get("id");
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("MobSpawner")) { if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals("MobSpawner")) {
throw new DataException("'MobSpawner' tile entity expected"); throw new DataException("'MobSpawner' tile entity expected");

Datei anzeigen

@ -15,27 +15,30 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.blocks; 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.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 * @author sk89q
*/ */
public class NoteBlock extends BaseBlock implements TileEntityBlock { public class NoteBlock extends BaseBlock implements TileEntityBlock {
/**
* Stores the pitch.
*/
private byte note; private byte note;
/** /**
* Construct the note block. * Construct the note block with a data value of 0.
*/ */
public NoteBlock() { public NoteBlock() {
super(BlockID.NOTE_BLOCK); super(BlockID.NOTE_BLOCK);
@ -43,9 +46,9 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
} }
/** /**
* Construct the note block. * Construct the note block with a given data value.
* *
* @param data * @param data data value
*/ */
public NoteBlock(int data) { public NoteBlock(int data) {
super(BlockID.NOTE_BLOCK, data); super(BlockID.NOTE_BLOCK, data);
@ -53,10 +56,10 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
} }
/** /**
* Construct the note block. * Construct the note block with a given data value and note.
* *
* @param data * @param data data value
* @param note * @param note note
*/ */
public NoteBlock(int data, byte note) { public NoteBlock(int data, byte note) {
super(BlockID.NOTE_BLOCK, data); super(BlockID.NOTE_BLOCK, data);
@ -64,6 +67,8 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
} }
/** /**
* Get the note.
*
* @return the note * @return the note
*/ */
public byte getNote() { public byte getNote() {
@ -71,50 +76,44 @@ public class NoteBlock extends BaseBlock implements TileEntityBlock {
} }
/** /**
* Set the note.
*
* @param note the note to set * @param note the note to set
*/ */
public void setNote(byte note) { public void setNote(byte note) {
this.note = note; this.note = note;
} }
/** @Override
* Return the name of the title entity ID. public boolean hasNbtData() {
* return true;
* @return title entity ID }
*/
public String getTileEntityID() { @Override
public String getNbtId() {
return "Music"; return "Music";
} }
/** @Override
* Store additional tile entity data. Returns true if the data is used. public CompoundTag getNbtData() {
*
* @return map of values
* @throws DataException
*/
public Map<String, Tag> toTileEntityNBT()
throws DataException {
Map<String, Tag> values = new HashMap<String, Tag>(); Map<String, Tag> values = new HashMap<String, Tag>();
values.put("note", new ByteTag("note", note)); values.put("note", new ByteTag("note", note));
return values; return new CompoundTag(getNbtId(), values);
} }
/** @Override
* Get additional information from the title entity data. public void setNbtData(CompoundTag rootTag) throws DataException {
* if (rootTag == null) {
* @param values
* @throws DataException
*/
public void fromTileEntityNBT(Map<String, Tag> values)
throws DataException {
if (values == null) {
return; return;
} }
Map<String, Tag> values = rootTag.getValue();
Tag t; Tag t;
t = values.get("id"); 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"); throw new DataException("'Music' tile entity expected");
} }

Datei anzeigen

@ -15,30 +15,32 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.blocks; 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.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 * @author sk89q
*/ */
public class SignBlock extends BaseBlock implements TileEntityBlock { public class SignBlock extends BaseBlock implements TileEntityBlock {
/**
* Stores the sign's text.
*/
private String[] text; private String[] text;
/** /**
* Construct the sign without text. * Construct the sign without text.
* *
* @param type * @param type type ID
* @param data * @param data data value (orientation)
*/ */
public SignBlock(int type, int data) { public SignBlock(int type, int data) {
super(type, data); super(type, data);
@ -48,16 +50,21 @@ public class SignBlock extends BaseBlock implements TileEntityBlock {
/** /**
* Construct the sign with text. * Construct the sign with text.
* *
* @param type * @param type type ID
* @param data * @param data data value (orientation)
* @param text * @param text lines of text
*/ */
public SignBlock(int type, int data, String[] text) { public SignBlock(int type, int data, String[] text) {
super(type, data); super(type, data);
if (text == null) {
this.text = new String[] { "", "", "", "" };
}
this.text = text; this.text = text;
} }
/** /**
* Get the text.
*
* @return the text * @return the text
*/ */
public String[] getText() { public String[] getText() {
@ -65,55 +72,52 @@ public class SignBlock extends BaseBlock implements TileEntityBlock {
} }
/** /**
* Set the text.
*
* @param text the text to set * @param text the text to set
*/ */
public void setText(String[] text) { public void setText(String[] text) {
if (text == null) {
throw new IllegalArgumentException("Can't set null text for a sign");
}
this.text = text; this.text = text;
} }
/** @Override
* Return the name of the title entity ID. public boolean hasNbtData() {
* return true;
* @return title entity ID }
*/
public String getTileEntityID() { @Override
public String getNbtId() {
return "Sign"; return "Sign";
} }
/** @Override
* Store additional tile entity data. Returns true if the data is used. public CompoundTag getNbtData() {
*
* @return map of values
* @throws DataException
*/
public Map<String, Tag> toTileEntityNBT()
throws DataException {
Map<String, Tag> values = new HashMap<String, Tag>(); Map<String, Tag> values = new HashMap<String, Tag>();
values.put("Text1", new StringTag("Text1", text[0])); values.put("Text1", new StringTag("Text1", text[0]));
values.put("Text2", new StringTag("Text2", text[1])); values.put("Text2", new StringTag("Text2", text[1]));
values.put("Text3", new StringTag("Text3", text[2])); values.put("Text3", new StringTag("Text3", text[2]));
values.put("Text4", new StringTag("Text4", text[3])); values.put("Text4", new StringTag("Text4", text[3]));
return values; return new CompoundTag(getNbtId(), values);
} }
/** @Override
* Get additional information from the title entity data. public void setNbtData(CompoundTag rootTag) throws DataException {
* if (rootTag == null) {
* @param values
* @throws DataException
*/
public void fromTileEntityNBT(Map<String, Tag> values)
throws DataException {
if (values == null) {
return; return;
} }
Map<String, Tag> values = rootTag.getValue();
Tag t; Tag t;
text = new String[] { "", "", "", "" }; text = new String[] { "", "", "", "" };
t = values.get("id"); 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"); throw new DataException("'Sign' tile entity expected");
} }

Datei anzeigen

@ -1,7 +1,7 @@
// $Id$ // $Id$
/* /*
* WorldEdit * WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com> and contributors * Copyright (C) sk89q <http://www.sk89q.com> and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -19,42 +19,22 @@
package com.sk89q.worldedit.blocks; package com.sk89q.worldedit.blocks;
import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.foundation.NbtValued;
import com.sk89q.worldedit.data.*;
import java.util.Map;
/** /**
* 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 * @author sk89q
*/ */
public interface TileEntityBlock { public interface TileEntityBlock extends NbtValued {
/** /**
* Return the name of the title entity ID. * Return the name of the title entity ID.
* *
* @return tile entity ID * @return tile entity ID, non-null string
*/ */
public abstract String getTileEntityID(); String getNbtId();
/**
* Store additional tile entity data.
*
* @return map of values
* @throws DataException When invalid data is encountered
*/
public abstract Map<String, Tag> 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<String, Tag> values)
throws DataException;
} }

Datei anzeigen

@ -27,17 +27,20 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sk89q.worldedit.LocalEntity; import org.bukkit.Effect;
import com.sk89q.worldedit.WorldEdit; import org.bukkit.Location;
import com.sk89q.worldedit.bukkit.entity.BukkitEntity; import org.bukkit.Material;
import com.sk89q.worldedit.util.TreeGenerator; import org.bukkit.TreeType;
import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.Chest; import org.bukkit.block.Chest;
import org.bukkit.block.Furnace;
import org.bukkit.block.CreatureSpawner; import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.Furnace;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Animals; import org.bukkit.entity.Animals;
@ -56,24 +59,34 @@ import org.bukkit.entity.Tameable;
import org.bukkit.inventory.DoubleChestInventory; import org.bukkit.inventory.DoubleChestInventory;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; 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.BiomeType;
import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.LocalEntity;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.EntityType; 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.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator;
public class BukkitWorld extends LocalWorld { public class BukkitWorld extends LocalWorld {
private static final Logger logger = Logger.getLogger(BukkitWorld.class.getCanonicalName());
private World world; private World world;
private boolean skipNmsAccess = false;
private boolean skipNmsSafeSet = false;
/** /**
* Construct the object. * Construct the object.
@ -211,6 +224,7 @@ public class BukkitWorld extends LocalWorld {
* @param pt * @param pt
* @return * @return
*/ */
@Override
public BiomeType getBiome(Vector2D pt) { public BiomeType getBiome(Vector2D pt) {
Biome bukkitBiome = world.getBiome(pt.getBlockX(), pt.getBlockZ()); Biome bukkitBiome = world.getBiome(pt.getBlockX(), pt.getBlockZ());
try { try {
@ -340,6 +354,15 @@ public class BukkitWorld extends LocalWorld {
return true; 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; return false;
} }
@ -400,6 +423,7 @@ public class BukkitWorld extends LocalWorld {
org.bukkit.block.NoteBlock bukkit = (org.bukkit.block.NoteBlock) state; org.bukkit.block.NoteBlock bukkit = (org.bukkit.block.NoteBlock) state;
NoteBlock we = (NoteBlock) block; NoteBlock we = (NoteBlock) block;
we.setNote(bukkit.getRawNote()); we.setNote(bukkit.getRawNote());
return true;
} }
return false; return false;
@ -902,6 +926,7 @@ public class BukkitWorld extends LocalWorld {
world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally(); world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally();
} }
@Override
public LocalEntity[] getEntities(Region region) { public LocalEntity[] getEntities(Region region) {
List<BukkitEntity> entities = new ArrayList<BukkitEntity>(); List<BukkitEntity> entities = new ArrayList<BukkitEntity>();
for (Vector2D pt : region.getChunks()) { for (Vector2D pt : region.getChunks()) {
@ -917,6 +942,7 @@ public class BukkitWorld extends LocalWorld {
return entities.toArray(new BukkitEntity[entities.size()]); return entities.toArray(new BukkitEntity[entities.size()]);
} }
@Override
public int killEntities(LocalEntity... entities) { public int killEntities(LocalEntity... entities) {
int amount = 0; int amount = 0;
Set<UUID> toKill = new HashSet<UUID>(); Set<UUID> toKill = new HashSet<UUID>();
@ -931,4 +957,52 @@ public class BukkitWorld extends LocalWorld {
} }
return amount; 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);
}
} }

Datei anzeigen

@ -0,0 +1,360 @@
// $Id$
/*
* This file is a part of WorldEdit.
* Copyright (c) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
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.
* </p>
* 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<String, Tag>());
}
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<String, Tag> values = new HashMap<String, Tag>();
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<Tag> values = new ArrayList<Tag>();
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<String, Tag> 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());
}
}
}

Datei anzeigen

@ -182,12 +182,12 @@ public class AnvilChunk implements Chunk {
* @return * @return
* @throws DataException * @throws DataException
*/ */
private Map<String, Tag> getBlockTileEntity(Vector pos) throws DataException { private CompoundTag getBlockTileEntity(Vector pos) throws DataException {
if (tileEntities == null) { if (tileEntities == null) {
populateTileEntities(); populateTileEntities();
} }
return tileEntities.get(new BlockVector(pos)); return new CompoundTag("", tileEntities.get(new BlockVector(pos)));
} }
@Override @Override
@ -213,8 +213,8 @@ public class AnvilChunk implements Chunk {
} }
if (block instanceof TileEntityBlock) { if (block instanceof TileEntityBlock) {
Map<String, Tag> tileEntity = getBlockTileEntity(pos); CompoundTag tileEntity = getBlockTileEntity(pos);
((TileEntityBlock) block).fromTileEntityNBT(tileEntity); ((TileEntityBlock) block).setNbtData(tileEntity);
} }
return block; return block;

Datei anzeigen

@ -19,12 +19,28 @@
package com.sk89q.worldedit.data; package com.sk89q.worldedit.data;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
import com.sk89q.jnbt.*; import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.worldedit.*; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.*; 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. * Represents a chunk.
@ -164,12 +180,12 @@ public class OldChunk implements Chunk {
* @return * @return
* @throws DataException * @throws DataException
*/ */
private Map<String, Tag> getBlockTileEntity(Vector pos) throws DataException { private CompoundTag getBlockTileEntity(Vector pos) throws DataException {
if (tileEntities == null) { if (tileEntities == null) {
populateTileEntities(); populateTileEntities();
} }
return tileEntities.get(new BlockVector(pos)); return new CompoundTag("", tileEntities.get(new BlockVector(pos)));
} }
@Override @Override
@ -195,8 +211,8 @@ public class OldChunk implements Chunk {
} }
if (block instanceof TileEntityBlock) { if (block instanceof TileEntityBlock) {
Map<String, Tag> tileEntity = getBlockTileEntity(pos); CompoundTag tileEntity = getBlockTileEntity(pos);
((TileEntityBlock) block).fromTileEntityNBT(tileEntity); ((TileEntityBlock) block).setNbtData(tileEntity);
} }
return block; return block;

Datei anzeigen

@ -16,7 +16,6 @@
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.foundation; package com.sk89q.worldedit.foundation;
import com.sk89q.jnbt.CompoundTag; 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 * Implementations can and should extend this class to allow native implementations
* of NBT data handling, primarily for performance reasons. Subclasses can only convert * 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 * 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 * overriding the NBT methods, {@link #getNbtId()} should be overridden too, otherwise
* the default implementation will invoke {@link #getNbtData()}, a potentially costly * the default implementation will invoke {@link #getNbtData()}, a potentially costly
* operation when it is not needed. Implementations may want to cache converted NBT data * 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 // Instances of this class should be _as small as possible_ because there will
// be millions of instances of this object. // be millions of instances of this object.
private short rawIdData; private short id;
private short data;
private CompoundTag nbtData; private CompoundTag nbtData;
/** /**
@ -114,7 +114,7 @@ public class Block implements TileEntityBlock {
* @return ID (between 0 and {@link #MAX_ID}) * @return ID (between 0 and {@link #MAX_ID})
*/ */
public int getId() { 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}). * @param id block id (between 0 and {@link #MAX_ID}).
*/ */
public void setId(int id) { public void setId(int id) {
if (id < MAX_ID) { if (id > MAX_ID) {
throw new IllegalArgumentException("Can't have a block ID above " + MAX_ID); throw new IllegalArgumentException("Can't have a block ID above "
+ MAX_ID + " (" + id + " given)");
} }
if (id < 0) { if (id < 0) {
throw new IllegalArgumentException("Can't have a block ID below 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) * @return data value (0-15)
*/ */
public int getData() { 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}). * @param data block data value (between 0 and {@link #MAX_DATA}).
*/ */
public void setData(int data) { public void setData(int data) {
if (data < MAX_DATA) { if (data > MAX_DATA) {
throw new IllegalArgumentException("Can't have a block data value above " + MAX_DATA); throw new IllegalArgumentException(
"Can't have a block data value above " + MAX_DATA + " ("
+ data + " given)");
} }
if (data < 0) { if (data < 0) {
throw new IllegalArgumentException("Can't have a block data value below 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); setData(data);
} }
/** @Override
* Returns whether the block contains NBT data.
*
* @return NBT data;
*/
public boolean hasNbtData() { public boolean hasNbtData() {
return getNbtData() != null; 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 @Override
public String getNbtId() { public String getNbtId() {
CompoundTag nbtData = getNbtData(); CompoundTag nbtData = getNbtData();

Datei anzeigen

@ -28,11 +28,21 @@ import com.sk89q.worldedit.data.DataException;
*/ */
public interface NbtValued { 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 * 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 * in any way, should be sent to {@link #setNbtData(CompoundTag)} so that
* the instance knows of the changes. Making changes without calling * the instance knows of the changes. Making changes without calling
* {@link #setNbtData(CompoundTag)} could have unintended consequences. * {@link #setNbtData(CompoundTag)} could have unintended consequences.
* </p>
* {@link #hasNbtData()} must return true if and only if method does not return null.
* *
* @return compound tag, or null * @return compound tag, or null
*/ */

Datei anzeigen

@ -18,6 +18,18 @@
package com.sk89q.worldedit.schematic; 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.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag; 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.blocks.TileEntityBlock;
import com.sk89q.worldedit.data.DataException; 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 * @author zml2008
*/ */
@ -176,7 +177,7 @@ public class MCEditSchematicFormat extends SchematicFormat {
BaseBlock block = getBlockForId(blocks[index], blockData[index]); BaseBlock block = getBlockForId(blocks[index], blockData[index]);
if (block instanceof TileEntityBlock && tileEntitiesMap.containsKey(pt)) { 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); clipboard.setBlock(pt, block);
} }
@ -239,19 +240,22 @@ public class MCEditSchematicFormat extends SchematicFormat {
// Store TileEntity data // Store TileEntity data
if (block instanceof TileEntityBlock) { if (block instanceof TileEntityBlock) {
TileEntityBlock tileEntityBlock = TileEntityBlock tileEntityBlock = block;
(TileEntityBlock) block;
// Get the list of key/values from the block // Get the list of key/values from the block
Map<String, Tag> values = tileEntityBlock.toTileEntityNBT(); CompoundTag rawTag = tileEntityBlock.getNbtData();
if (values != null) { if (rawTag != null) {
values.put("id", new StringTag("id", Map<String, Tag> values = new HashMap<String, Tag>();
tileEntityBlock.getTileEntityID())); for (Entry<String, Tag> 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("x", new IntTag("x", x));
values.put("y", new IntTag("y", y)); values.put("y", new IntTag("y", y));
values.put("z", new IntTag("z", z)); values.put("z", new IntTag("z", z));
CompoundTag tileEntityTag =
new CompoundTag("TileEntity", values); CompoundTag tileEntityTag = new CompoundTag("TileEntity", values);
tileEntities.add(tileEntityTag); tileEntities.add(tileEntityTag);
} }
} }