mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-11-02 02:47:11 +00:00
Implemented new Anvil saving format, fixed old chunk saving format.
- Added 'Chunk' Interface. - Moved old 'Chunk' to 'OldChunk' and replaced dynamic world height reference with '128. - Added 'AnvilChunk' implementing the new anvil chunk format. - Added temp fixes to FileMcRegionChunkStore.java, TrueZipMcRegionChunkStore.java and ZippedMcRegionChunkStore.java too allow them to read .mca files. - Added the new 'IntArrayTag' since the new heightmap tag wasn't recognized. - Moved 'getChildTag' to 'NBTUtils'.
This commit is contained in:
parent
19b353f6b5
commit
8aabfb0c67
87
src/main/java/com/sk89q/jnbt/IntArrayTag.java
Normal file
87
src/main/java/com/sk89q/jnbt/IntArrayTag.java
Normal file
@ -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 <code>TAG_Int_Array</code> 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();
|
||||
}
|
||||
|
||||
}
|
@ -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.
|
||||
|
@ -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 + ".");
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 extends Tag> T getChildTag(Map<String,Tag> items, String key,
|
||||
Class<T> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<String, Tag> 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<String, Tag> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<String, Tag> 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<String, Tag> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<String, Tag> 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<String, Tag> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
223
src/main/java/com/sk89q/worldedit/data/AnvilChunk.java
Normal file
223
src/main/java/com/sk89q/worldedit/data/AnvilChunk.java
Normal file
@ -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<BlockVector, Map<String,Tag>> 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<Tag> 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<Tag> tags = NBTUtils.getChildTag(
|
||||
rootTag.getValue(), "TileEntities", ListTag.class)
|
||||
.getValue();
|
||||
|
||||
tileEntities = new HashMap<BlockVector, Map<String, Tag>>();
|
||||
|
||||
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<String, Tag> values = new HashMap<String, Tag>();
|
||||
|
||||
for (Map.Entry<String, Tag> 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<String, Tag> 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<String, Tag> tileEntity = getBlockTileEntity(pos);
|
||||
((TileEntityBlock) block).fromTileEntityNBT(tileEntity);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
}
|
@ -1,75 +1,9 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com> 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<BlockVector, Map<String,Tag>> 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<Tag> tags = getChildTag(
|
||||
rootTag.getValue(), "TileEntities", ListTag.class)
|
||||
.getValue();
|
||||
|
||||
tileEntities = new HashMap<BlockVector, Map<String, Tag>>();
|
||||
|
||||
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<String, Tag> values = new HashMap<String, Tag>();
|
||||
|
||||
for (Map.Entry<String, Tag> 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<String, Tag> 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<String, Tag> 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 extends Tag> T getChildTag(Map<String,Tag> items, String key,
|
||||
Class<T> 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;
|
||||
}
|
||||
|
@ -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<String, Tag> tags = tag.getValue();
|
||||
if(tags.containsKey("Sections")) {
|
||||
return new AnvilChunk(world, tag);
|
||||
}
|
||||
return new OldChunk(world, tag);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
205
src/main/java/com/sk89q/worldedit/data/OldChunk.java
Normal file
205
src/main/java/com/sk89q/worldedit/data/OldChunk.java
Normal file
@ -0,0 +1,205 @@
|
||||
// $Id$
|
||||
/*
|
||||
* WorldEdit
|
||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com> 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<BlockVector, Map<String,Tag>> 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<Tag> tags = NBTUtils.getChildTag(
|
||||
rootTag.getValue(), "TileEntities", ListTag.class)
|
||||
.getValue();
|
||||
|
||||
tileEntities = new HashMap<BlockVector, Map<String, Tag>>();
|
||||
|
||||
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<String, Tag> values = new HashMap<String, Tag>();
|
||||
|
||||
for (Map.Entry<String, Tag> 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<String, Tag> 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<String, Tag> tileEntity = getBlockTileEntity(pos);
|
||||
((TileEntityBlock) block).fromTileEntityNBT(tileEntity);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user