heavily refactored Tag to be type safe and extendable: every tag has now one type entry and one own class, nothing else.
parent
e79f8856e3
commit
7d47a3ea85
|
@ -1,31 +1,25 @@
|
|||
package MoF;
|
||||
import amidst.Util;
|
||||
import amidst.nbt.Tag;
|
||||
import amidst.nbt.TagCompound;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
|
||||
public class SaveLoader {
|
||||
public static String genType = "default";
|
||||
public static FileFilter getFilter() {
|
||||
return (new FileFilter() {
|
||||
public boolean accept(File f) {
|
||||
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
String[] st = f.getName().split("\\/");
|
||||
if (st[st.length-1].toLowerCase().equals("level.dat"))
|
||||
return true;
|
||||
return false;
|
||||
if (f.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
String[] st = f.getName().split("\\/");
|
||||
return st[st.length - 1].equalsIgnoreCase("level.dat");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Minecraft Data File (level.dat)";
|
||||
|
@ -60,20 +54,19 @@ public class SaveLoader {
|
|||
return players;
|
||||
}
|
||||
public void movePlayer(String name, int x, int y) {
|
||||
File out = null;
|
||||
File out;
|
||||
if (multi) {
|
||||
String outpath = file.getParent() + "/players/" + name +".dat";
|
||||
out = new File(outpath);
|
||||
String outPath = file.getParent() + "/players/" + name +".dat";
|
||||
out = new File(outPath);
|
||||
backupFile(out);
|
||||
try {
|
||||
Tag t = Tag.readFrom(new FileInputStream(out));
|
||||
TagCompound t = Tag.readFrom(new FileInputStream(out));
|
||||
Tag pos = t.findTagByName("Pos");
|
||||
Tag[] pa = (Tag[]) pos.getValue();
|
||||
pa[0].setValue((double)x);
|
||||
pa[1].setValue((double)120);
|
||||
pa[2].setValue((double)y);
|
||||
Tag<Double>[] pa = (Tag[]) pos.getValue();
|
||||
pa[0].setValue((double) x);
|
||||
pa[1].setValue((double) 120);
|
||||
pa[2].setValue((double) y);
|
||||
t.writeTo(new FileOutputStream(out));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -82,35 +75,33 @@ public class SaveLoader {
|
|||
out = file;
|
||||
backupFile(out);
|
||||
try {
|
||||
Tag t = Tag.readFrom(new FileInputStream(out));
|
||||
TagCompound t = Tag.readFrom(new FileInputStream(out));
|
||||
Tag pos = t.findTagByName("Pos");
|
||||
Tag[] pa = (Tag[]) pos.getValue();
|
||||
pa[0].setValue((double)x);
|
||||
pa[1].setValue((double)120);
|
||||
pa[2].setValue((double)y);
|
||||
Tag<Double>[] pa = (Tag[]) pos.getValue();
|
||||
pa[0].setValue((double) x);
|
||||
pa[1].setValue((double) 120);
|
||||
pa[2].setValue((double) y);
|
||||
t.writeTo(new FileOutputStream(out));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void backupFile(File f) {
|
||||
File inputFile = f;
|
||||
File outputFile = new File(f.toString() + ".moth");
|
||||
if (!back.contains(outputFile.toString())) {
|
||||
try {
|
||||
FileReader in = new FileReader(inputFile);
|
||||
FileWriter out = new FileWriter(outputFile);
|
||||
int c;
|
||||
|
||||
while ((c = in.read()) != -1)
|
||||
out.write(c);
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
back.add(outputFile.toString());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
private void backupFile(File inputFile) {
|
||||
File outputFile = new File(inputFile.toString() + ".moth");
|
||||
if (!back.contains(outputFile.toString())) {
|
||||
try {
|
||||
FileReader in = new FileReader(inputFile);
|
||||
FileWriter out = new FileWriter(outputFile);
|
||||
int c;
|
||||
|
||||
while ((c = in.read()) != -1)
|
||||
out.write(c);
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
back.add(outputFile.toString());
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,35 +110,34 @@ public class SaveLoader {
|
|||
players = new ArrayList<Player>();
|
||||
back = new ArrayList<String>();
|
||||
try {
|
||||
Tag t = Tag.readFrom(new FileInputStream(f));
|
||||
Tag pTag = t.findTagByName("Player");
|
||||
seed = (Long)t.findTagByName("RandomSeed").getValue();
|
||||
genType = (String)t.findTagByName("generatorName").getValue();
|
||||
TagCompound t = Tag.readFrom(new FileInputStream(f));
|
||||
TagCompound pTag = (TagCompound) t.findTagByName("Player");
|
||||
seed = (Long) t.findTagByName("RandomSeed").getValue();
|
||||
genType = (String) t.findTagByName("generatorName").getValue();
|
||||
System.out.println("Gen Type: " + genType);
|
||||
if (pTag!=null) {
|
||||
if (pTag != null) {
|
||||
multi = false;
|
||||
Tag pos = pTag.findTagByName("Pos");
|
||||
Tag[] pa = (Tag[]) pos.getValue();
|
||||
double x = (Double) pa[0].getValue();
|
||||
double z = (Double) pa[2].getValue();
|
||||
players.add(new Player("Player", (int)x, (int)z));
|
||||
|
||||
Tag<Double>[] pa = (Tag[]) pos.getValue();
|
||||
double x = pa[0].getValue();
|
||||
double z = pa[2].getValue();
|
||||
players.add(new Player("Player", (int) x, (int) z));
|
||||
} else {
|
||||
multi = true;
|
||||
File[] listing = new File(f.getParent() + "/players").listFiles();
|
||||
Tag ps;
|
||||
for (int i = 0; i < listing.length; i++) {
|
||||
TagCompound ps;
|
||||
for (int i = 0; i < (listing != null ? listing.length : 0); i++) {
|
||||
ps = Tag.readFrom(new FileInputStream(listing[i]));
|
||||
Tag pos = ps.findTagByName("Pos");
|
||||
Tag[] pa = (Tag[]) pos.getValue();
|
||||
double x = (Double) pa[0].getValue();
|
||||
double z = (Double) pa[2].getValue();
|
||||
players.add(new Player(listing[i].getName().split("\\.")[0], (int)x, (int)z));
|
||||
Tag<Double>[] pa = (Tag[]) pos.getValue();
|
||||
double x = pa[0].getValue();
|
||||
double z = pa[2].getValue();
|
||||
players.add(new Player(listing[i].getName().split("\\.")[0], (int) x, (int) z));
|
||||
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// FIXME Dialog when file read fails.
|
||||
Util.showError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package amidst;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class Util {
|
||||
/** Shows an error message for an exception
|
||||
* @param e the exception for which the stachtrace is to be shown
|
||||
*/
|
||||
public static void showError(Exception e) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintStream ps = new PrintStream(baos);
|
||||
e.printStackTrace(ps);
|
||||
String trace = baos.toString();
|
||||
|
||||
e.printStackTrace();
|
||||
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
trace,
|
||||
e.toString(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// try {
|
||||
// int infinity = 1 / 0;
|
||||
// } catch (Exception e) {
|
||||
// showError(e);
|
||||
// }
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public abstract class SequenceTagBase<T> extends Tag<Tag<T>[]> {
|
||||
SequenceTagBase(Type type, String name, Tag<T>[] value) {
|
||||
super(type, name, value);
|
||||
}
|
||||
|
||||
public abstract void addTag(Tag<T> tag);
|
||||
|
||||
/** Add a tag to a TAG_List or a TAG_Compound at the specified index.
|
||||
*/
|
||||
public void insertTag(Tag<T> tag, int index) {
|
||||
if (value.length > 0 && (this instanceof TagList && tag.type != ((TagList) this).listType))
|
||||
throw new IllegalArgumentException();
|
||||
if (index > value.length)
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
||||
Tag<T>[] newValue = new Tag[value.length + 1];
|
||||
System.arraycopy(value, 0, newValue, 0, index);
|
||||
newValue[index] = tag;
|
||||
System.arraycopy(value, index, newValue, index + 1, value.length - index);
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
/** Remove a tag from a TAG_List or a TAG_Compound at the specified index.
|
||||
*
|
||||
* @return the removed tag
|
||||
*/
|
||||
public Tag<T> removeTag(int index) {
|
||||
if (type != Type.TAG_List && type != Type.TAG_Compound)
|
||||
throw new RuntimeException();
|
||||
|
||||
Tag<T> victim = value[index];
|
||||
Tag<T>[] newValue = new Tag[value.length - 1];
|
||||
System.arraycopy(value, 0, newValue, 0, index);
|
||||
index++;
|
||||
System.arraycopy(value, index, newValue, index - 1, value.length - index);
|
||||
|
||||
value = newValue;
|
||||
return victim;
|
||||
}
|
||||
|
||||
/** Remove a tag from a TAG_List or a TAG_Compound. If the tag is not a child of this tag then nested tags are searched.
|
||||
*
|
||||
* @param tag tag to look for
|
||||
*/
|
||||
public void removeSubTag(Tag<T> tag) {
|
||||
if (tag == null) return;
|
||||
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (value[i] == tag) {
|
||||
removeTag(i);
|
||||
return;
|
||||
} else {
|
||||
if (value[i] instanceof SequenceTagBase) {
|
||||
((SequenceTagBase<T>) value[i]).removeSubTag(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first nested tag with specified name in a TAG_List or TAG_Compound after a tag with the same name.
|
||||
*
|
||||
* @param name the name to look for. May be null to look for unnamed tags.
|
||||
* @param found the previously found tag with the same name.
|
||||
* @return the first nested tag that has the specified name after the previously found tag.
|
||||
*/
|
||||
public Tag<T> findNextTagByName(String name, Tag<T> found) {
|
||||
for (Tag<T> subTag : value) {
|
||||
if ((subTag.name == null && name == null) //End tag
|
||||
|| (subTag.name != null && subTag.name.equals(name))) {
|
||||
return subTag;
|
||||
} else if (subTag instanceof TagCompound) {
|
||||
Tag<T> newFound = ((TagCompound) subTag).findTagByName(name);
|
||||
if (newFound != null && newFound != found)
|
||||
return newFound;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void serializeEntries(PrintStream ps, int indent) {
|
||||
serializeIndented(ps, indent, "{");
|
||||
for (Tag st : value)
|
||||
st.serialize(ps, indent + 1);
|
||||
serializeIndented(ps, indent, "}");
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
|
@ -13,308 +13,68 @@ import java.util.zip.GZIPOutputStream;
|
|||
*
|
||||
* @see <a href="http://www.minecraft.net/docs/NBT.txt">Online NBT specification</a>
|
||||
*/
|
||||
public class Tag {
|
||||
private final Type type;
|
||||
private Type listType = null;
|
||||
private final String name;
|
||||
private Object value;
|
||||
public abstract class Tag<T> {
|
||||
public final Type type;
|
||||
public final String name;
|
||||
T value;
|
||||
|
||||
/**
|
||||
* Enum for the tag types.
|
||||
*/
|
||||
public enum Type {
|
||||
TAG_End,
|
||||
TAG_Byte,
|
||||
TAG_Short,
|
||||
TAG_Int,
|
||||
TAG_Long,
|
||||
TAG_Float,
|
||||
TAG_Double,
|
||||
TAG_Byte_Array,
|
||||
TAG_String,
|
||||
TAG_List,
|
||||
TAG_Compound,
|
||||
TAG_Int_Array
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TAG_List or TAG_Compound NBT tag.
|
||||
*
|
||||
* @param type either TAG_List or TAG_Compound
|
||||
* @param name name for the new tag or null to create an unnamed tag.
|
||||
* @param value list of tags to add to the new tag.
|
||||
*/
|
||||
public Tag(Type type, String name, Tag[] value) {
|
||||
this(type, name, (Object) value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TAG_List with an empty list. Use {@link Tag#addTag(Tag)} to add tags later.
|
||||
*
|
||||
* @param name name for this tag or null to create an unnamed tag.
|
||||
* @param listType type of the elements in this empty list.
|
||||
*/
|
||||
public Tag(String name, Type listType) {
|
||||
this(Type.TAG_List, name, listType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NBT tag.
|
||||
*
|
||||
* @param type any value from the {@link Type} enum.
|
||||
* @param name name for the new tag or null to create an unnamed tag.
|
||||
* @param value an object that fits the tag type or a {@link Type} to create an empty TAG_List with this list type.
|
||||
*/
|
||||
public Tag(Type type, String name, Object value) {
|
||||
switch (type) {
|
||||
case TAG_End:
|
||||
if (value != null)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Byte:
|
||||
if (!(value instanceof Byte))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Short:
|
||||
if (!(value instanceof Short))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Int:
|
||||
if (!(value instanceof Integer))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Long:
|
||||
if (!(value instanceof Long))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Float:
|
||||
if (!(value instanceof Float))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Double:
|
||||
if (!(value instanceof Double))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Byte_Array:
|
||||
if (!(value instanceof byte[]))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_String:
|
||||
if (!(value instanceof String))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_List:
|
||||
if (value instanceof Type) {
|
||||
this.listType = (Type) value;
|
||||
value = new Tag[0];
|
||||
} else {
|
||||
if (!(value instanceof Tag[]))
|
||||
throw new IllegalArgumentException();
|
||||
this.listType = (((Tag[]) value)[0]).getType();
|
||||
}
|
||||
break;
|
||||
case TAG_Compound:
|
||||
if (!(value instanceof Tag[]))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
//TODO: Int_Array
|
||||
TAG_End(TagEnd.class),
|
||||
TAG_Byte(TagByte.class),
|
||||
TAG_Short(TagShort.class),
|
||||
TAG_Int(TagInt.class),
|
||||
TAG_Long(TagLong.class),
|
||||
TAG_Float(TagFloat.class),
|
||||
TAG_Double(TagDouble.class),
|
||||
TAG_Byte_Array(TagByteArray.class),
|
||||
TAG_String(TagString.class),
|
||||
TAG_List(TagList.class),
|
||||
TAG_Compound(TagCompound.class),
|
||||
TAG_Int_Array(TagIntArray.class);
|
||||
|
||||
final Class<? extends Tag> clazz;
|
||||
|
||||
private Type(Class<? extends Tag> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public Tag readFrom(String name, DataInputStream dis) {
|
||||
try {
|
||||
Constructor<? extends Tag> c = clazz.getDeclaredConstructor(String.class, DataInputStream.class);
|
||||
return c.newInstance(name, dis);
|
||||
} catch (NoSuchMethodException e) { //TODO: maybe java 7 for multicatch?
|
||||
throw new RuntimeException(name, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(name, e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(name, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(name, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Type fromByte(Byte type) {
|
||||
return Type.values()[type];
|
||||
}
|
||||
}
|
||||
|
||||
Tag(Type type, String name, T value) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object newValue) {
|
||||
switch (type) {
|
||||
case TAG_End:
|
||||
if (value != null)
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Byte:
|
||||
if (!(value instanceof Byte))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Short:
|
||||
if (!(value instanceof Short))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Int:
|
||||
if (!(value instanceof Integer))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Long:
|
||||
if (!(value instanceof Long))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Float:
|
||||
if (!(value instanceof Float))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Double:
|
||||
if (!(value instanceof Double))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_Byte_Array:
|
||||
if (!(value instanceof byte[]))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_String:
|
||||
if (!(value instanceof String))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
case TAG_List:
|
||||
if (value instanceof Type) {
|
||||
this.listType = (Type) value;
|
||||
value = new Tag[0];
|
||||
} else {
|
||||
if (!(value instanceof Tag[]))
|
||||
throw new IllegalArgumentException();
|
||||
this.listType = (((Tag[]) value)[0]).getType();
|
||||
}
|
||||
break;
|
||||
case TAG_Compound:
|
||||
if (!(value instanceof Tag[]))
|
||||
throw new IllegalArgumentException();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
//TODO: Int_Array
|
||||
}
|
||||
|
||||
public void setValue(T newValue) {
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
public Type getListType() {
|
||||
return listType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tag to a TAG_List or a TAG_Compound.
|
||||
*/
|
||||
public void addTag(Tag tag) {
|
||||
if (type != Type.TAG_List && type != Type.TAG_Compound)
|
||||
throw new RuntimeException();
|
||||
Tag[] subtags = (Tag[]) value;
|
||||
|
||||
int index = subtags.length;
|
||||
|
||||
//For TAG_Compund entries, we need to add the tag BEFORE the end,
|
||||
//or the new tag gets placed after the TAG_End, messing up the data.
|
||||
//TAG_End MUST be kept at the very end of the TAG_Compound.
|
||||
if(type == Type.TAG_Compound) index--;
|
||||
insertTag(tag, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tag to a TAG_List or a TAG_Compound at the specified index.
|
||||
*/
|
||||
public void insertTag(Tag tag, int index) {
|
||||
if (type != Type.TAG_List && type != Type.TAG_Compound)
|
||||
throw new RuntimeException();
|
||||
Tag[] subtags = (Tag[]) value;
|
||||
if (subtags.length > 0)
|
||||
if (type == Type.TAG_List && tag.getType() != getListType())
|
||||
throw new IllegalArgumentException();
|
||||
if (index > subtags.length)
|
||||
throw new IndexOutOfBoundsException();
|
||||
Tag[] newValue = new Tag[subtags.length + 1];
|
||||
System.arraycopy(subtags, 0, newValue, 0, index);
|
||||
newValue[index] = tag;
|
||||
System.arraycopy(subtags, index, newValue, index + 1, subtags.length - index);
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a tag from a TAG_List or a TAG_Compound at the specified index.
|
||||
*
|
||||
* @return the removed tag
|
||||
*/
|
||||
public Tag removeTag(int index) {
|
||||
if (type != Type.TAG_List && type != Type.TAG_Compound)
|
||||
throw new RuntimeException();
|
||||
Tag[] subtags = (Tag[]) value;
|
||||
Tag victim = subtags[index];
|
||||
Tag[] newValue = new Tag[subtags.length - 1];
|
||||
System.arraycopy(subtags, 0, newValue, 0, index);
|
||||
index++;
|
||||
System.arraycopy(subtags, index, newValue, index - 1, subtags.length - index);
|
||||
value = newValue;
|
||||
return victim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a tag from a TAG_List or a TAG_Compound. If the tag is not a child of this tag then nested tags are searched.
|
||||
*
|
||||
* @param tag tag to look for
|
||||
*/
|
||||
public void removeSubTag(Tag tag) {
|
||||
if (type != Type.TAG_List && type != Type.TAG_Compound)
|
||||
throw new RuntimeException();
|
||||
if (tag == null)
|
||||
return;
|
||||
Tag[] subtags = (Tag[]) value;
|
||||
for (int i = 0; i < subtags.length; i++) {
|
||||
if (subtags[i] == tag) {
|
||||
removeTag(i);
|
||||
return;
|
||||
} else {
|
||||
if (subtags[i].type == Type.TAG_List || subtags[i].type == Type.TAG_Compound) {
|
||||
subtags[i].removeSubTag(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first nested tag with specified name in a TAG_Compound.
|
||||
*
|
||||
* @param name the name to look for. May be null to look for unnamed tags.
|
||||
* @return the first nested tag that has the specified name.
|
||||
*/
|
||||
public Tag findTagByName(String name) {
|
||||
return findNextTagByName(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first nested tag with specified name in a TAG_List or TAG_Compound after a tag with the same name.
|
||||
*
|
||||
* @param name the name to look for. May be null to look for unnamed tags.
|
||||
* @param found the previously found tag with the same name.
|
||||
* @return the first nested tag that has the specified name after the previously found tag.
|
||||
*/
|
||||
public Tag findNextTagByName(String name, Tag found) {
|
||||
if (type != Type.TAG_List && type != Type.TAG_Compound)
|
||||
return null;
|
||||
Tag[] subtags = (Tag[]) value;
|
||||
for (Tag subtag : subtags) {
|
||||
if ((subtag.name == null && name == null) || (subtag.name != null && subtag.name.equals(name))) {
|
||||
return subtag;
|
||||
} else {
|
||||
Tag newFound = subtag.findTagByName(name);
|
||||
if (newFound != null)
|
||||
if (newFound == found)
|
||||
continue;
|
||||
else
|
||||
return newFound;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a tag and its nested tags from an InputStream.
|
||||
*
|
||||
|
@ -322,76 +82,17 @@ public class Tag {
|
|||
* @return NBT tag or structure read from the InputStream
|
||||
* @throws java.io.IOException if there was no valid NBT structure in the InputStream or if another IOException occurred.
|
||||
*/
|
||||
public static Tag readFrom(InputStream is) throws IOException {
|
||||
public static TagCompound readFrom(InputStream is) throws IOException {
|
||||
DataInputStream dis = new DataInputStream(new GZIPInputStream(is));
|
||||
byte type = dis.readByte();
|
||||
Tag tag;
|
||||
Type type = Type.fromByte(dis.readByte());
|
||||
if (type != Type.TAG_Compound)
|
||||
throw new IOException("Root tags have to be Compound tags");
|
||||
|
||||
if (type == 0) {
|
||||
tag = new Tag(Type.TAG_End, null, null);
|
||||
} else {
|
||||
tag = new Tag(Type.values()[type], dis.readUTF(), readPayload(dis, type));
|
||||
}
|
||||
|
||||
dis.close();
|
||||
|
||||
return tag;
|
||||
TagCompound root = (TagCompound) Type.TAG_Compound.readFrom(dis.readUTF(), dis);
|
||||
is.close();
|
||||
return root;
|
||||
}
|
||||
|
||||
private static Object readPayload(DataInputStream dis, byte type) throws IOException {
|
||||
switch (Type.values()[type]) {
|
||||
case TAG_End:
|
||||
return null;
|
||||
case TAG_Byte:
|
||||
return dis.readByte();
|
||||
case TAG_Short:
|
||||
return dis.readShort();
|
||||
case TAG_Int:
|
||||
return dis.readInt();
|
||||
case TAG_Long:
|
||||
return dis.readLong();
|
||||
case TAG_Float:
|
||||
return dis.readFloat();
|
||||
case TAG_Double:
|
||||
return dis.readDouble();
|
||||
case TAG_Byte_Array:
|
||||
int length = dis.readInt();
|
||||
byte[] ba = new byte[length];
|
||||
dis.readFully(ba);
|
||||
return ba;
|
||||
case TAG_String:
|
||||
return dis.readUTF();
|
||||
case TAG_List:
|
||||
byte lt = dis.readByte();
|
||||
int ll = dis.readInt();
|
||||
Tag[] lo = new Tag[ll];
|
||||
for (int i = 0; i < ll; i++) {
|
||||
lo[i] = new Tag(Type.values()[lt], null, readPayload(dis, lt));
|
||||
}
|
||||
if (lo.length == 0)
|
||||
return Type.values()[lt];
|
||||
else
|
||||
return lo;
|
||||
case TAG_Compound:
|
||||
byte stt;
|
||||
Tag[] tags = new Tag[0];
|
||||
do {
|
||||
stt = dis.readByte();
|
||||
String name = null;
|
||||
if (stt != 0) {
|
||||
name = dis.readUTF();
|
||||
}
|
||||
Tag[] newTags = new Tag[tags.length + 1];
|
||||
System.arraycopy(tags, 0, newTags, 0, tags.length);
|
||||
newTags[tags.length] = new Tag(Type.values()[stt], name, readPayload(dis, stt));
|
||||
tags = newTags;
|
||||
} while (stt != 0);
|
||||
return tags;
|
||||
//TODO: Int_Array
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a tag and its nested tags from an InputStream.
|
||||
*
|
||||
|
@ -409,106 +110,50 @@ public class Tag {
|
|||
gzos.flush();
|
||||
gzos.close();
|
||||
}
|
||||
|
||||
private void writePayload(DataOutputStream dos) throws IOException {
|
||||
switch (type) {
|
||||
case TAG_End:
|
||||
break;
|
||||
case TAG_Byte:
|
||||
dos.writeByte((Byte) value);
|
||||
break;
|
||||
case TAG_Short:
|
||||
dos.writeShort((Short) value);
|
||||
break;
|
||||
case TAG_Int:
|
||||
dos.writeInt((Integer) value);
|
||||
break;
|
||||
case TAG_Long:
|
||||
dos.writeLong((Long) value);
|
||||
break;
|
||||
case TAG_Float:
|
||||
dos.writeFloat((Float) value);
|
||||
break;
|
||||
case TAG_Double:
|
||||
dos.writeDouble((Double) value);
|
||||
break;
|
||||
case TAG_Byte_Array:
|
||||
byte[] ba = (byte[]) value;
|
||||
dos.writeInt(ba.length);
|
||||
dos.write(ba);
|
||||
break;
|
||||
case TAG_String:
|
||||
dos.writeUTF((String) value);
|
||||
break;
|
||||
case TAG_List:
|
||||
Tag[] list = (Tag[]) value;
|
||||
dos.writeByte(getListType().ordinal());
|
||||
dos.writeInt(list.length);
|
||||
for (Tag tt : list) {
|
||||
tt.writePayload(dos);
|
||||
}
|
||||
break;
|
||||
case TAG_Compound:
|
||||
Tag[] subtags = (Tag[]) value;
|
||||
for (Tag st : subtags) {
|
||||
Tag subtag = st;
|
||||
Type type = subtag.getType();
|
||||
dos.writeByte(type.ordinal());
|
||||
if (type != Type.TAG_End) {
|
||||
dos.writeUTF(subtag.getName());
|
||||
subtag.writePayload(dos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
//TODO: Int_Array
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the NBT structure to System.out
|
||||
abstract void writePayload(DataOutputStream dos) throws IOException;
|
||||
|
||||
/** Print the NBT structure to System.out
|
||||
*/
|
||||
public void print() {
|
||||
print(this, 0);
|
||||
public void serialize() {
|
||||
serialize(System.out, 0);
|
||||
}
|
||||
|
||||
/** Prints an indented sequence of objects to a PrintStream, terminated by a newline
|
||||
* @param ps PrintStream to serialize to
|
||||
* @param indent Indentation level (2 spaces per level are printed)
|
||||
* @param line Things to serialize after the indentation
|
||||
*/
|
||||
static void serializeIndented(PrintStream ps, int indent, Object... line) {
|
||||
for (int i = 0; i < indent; i++)
|
||||
ps.print(" ");
|
||||
for (Object thing : line)
|
||||
if (thing != null)
|
||||
if (thing instanceof Object[])
|
||||
for (Object underThing : (Object[]) thing)
|
||||
ps.print(underThing);
|
||||
else
|
||||
ps.print(thing);
|
||||
ps.println();
|
||||
}
|
||||
|
||||
private void indent(int indent) {
|
||||
for (int i = 0; i < indent; i++) {
|
||||
System.out.print(" ");
|
||||
}
|
||||
/** Prints this Tag’s information and the sequence of Objects to a Prinstream, terminated by a newline
|
||||
* @param ps PrintStream to serialize to
|
||||
* @param indent Indentation level (2 spaces per level are printed)
|
||||
* @param line Things to serialize after the indentation and prefix
|
||||
*/
|
||||
void serializePrefix(PrintStream ps, int indent, Object... line) {
|
||||
if (type == Type.TAG_End) return;
|
||||
String suffix = (name == null) ? null : "(\"" + name + "\")";
|
||||
serializeIndented(ps, indent, type, suffix, line);
|
||||
}
|
||||
|
||||
private void print(Tag t, int indent) {
|
||||
Type type = t.getType();
|
||||
if (type == Type.TAG_End)
|
||||
return;
|
||||
String name = t.getName();
|
||||
indent(indent);
|
||||
System.out.print(t.getType());
|
||||
if (name != null)
|
||||
System.out.print("(\"" + t.getName() + "\")");
|
||||
if (type == Type.TAG_Byte_Array) {
|
||||
byte[] b = (byte[]) t.getValue();
|
||||
System.out.println(": [" + b.length + " bytes]");
|
||||
} else if (type == Type.TAG_List) {
|
||||
Tag[] subtags = (Tag[]) t.getValue();
|
||||
System.out.println(": " + subtags.length + " entries of type " + t.getListType());
|
||||
for (Tag st : subtags) {
|
||||
print(st, indent + 1);
|
||||
}
|
||||
indent(indent);
|
||||
System.out.println("}");
|
||||
} else if (type == Type.TAG_Compound) {
|
||||
Tag[] subtags = (Tag[]) t.getValue();
|
||||
System.out.println(": " + (subtags.length - 1) + " entries");
|
||||
indent(indent);
|
||||
System.out.println("{");
|
||||
for (Tag st : subtags) {
|
||||
print(st, indent + 1);
|
||||
}
|
||||
indent(indent);
|
||||
System.out.println("}");
|
||||
} else {
|
||||
System.out.println(": " + t.getValue());
|
||||
}
|
||||
/** Serializes this Tag to a PrintStream
|
||||
* Default implementation for value-like Tags. Overridden in sequence Tags
|
||||
* @param ps PrintStream to serialize to
|
||||
* @param indent Indentation level (2 spaces per level are printed)
|
||||
*/
|
||||
void serialize(PrintStream ps, int indent) {
|
||||
serializePrefix(ps, indent, ": ", value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagByte extends Tag<Byte> {
|
||||
TagByte(String name, byte value) {
|
||||
super(Type.TAG_Byte, name, value);
|
||||
}
|
||||
|
||||
TagByte(String name, DataInputStream dis) throws IOException {
|
||||
this(name, dis.readByte());
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeByte(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class TagByteArray extends Tag<byte[]> {
|
||||
TagByteArray(String name, byte[] value) {
|
||||
super(Type.TAG_Byte_Array, name, value);
|
||||
}
|
||||
|
||||
TagByteArray(String name, DataInputStream dis) throws IOException {
|
||||
this(name, readPayload(dis));
|
||||
}
|
||||
|
||||
private static byte[] readPayload(DataInputStream dis) throws IOException {
|
||||
int length = dis.readInt();
|
||||
byte[] ba = new byte[length];
|
||||
dis.readFully(ba);
|
||||
return ba;
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeInt(value.length);
|
||||
dos.write(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
void serialize(PrintStream ps, int indent) {
|
||||
serializePrefix(ps, indent, ": [" + value.length + " bytes]");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TagCompound extends SequenceTagBase<Object> {
|
||||
/**
|
||||
* Create a new TAG_Compound NBT tag.
|
||||
*
|
||||
* @param name name for the new tag or null to create an unnamed tag.
|
||||
* @param value list of tags to add to the new tag.
|
||||
*/
|
||||
public TagCompound(String name, Tag[] value) {
|
||||
super(Type.TAG_Compound, name, value);
|
||||
}
|
||||
|
||||
TagCompound(String name, DataInputStream dis) throws IOException {
|
||||
this(name, readPayload(dis));
|
||||
}
|
||||
|
||||
private static Tag[] readPayload(DataInputStream dis) throws IOException {
|
||||
Type stt;
|
||||
List<Tag> tags = new ArrayList<Tag>();
|
||||
do {
|
||||
stt = Type.fromByte(dis.readByte());
|
||||
String name = null;
|
||||
if (stt != Type.TAG_End) {
|
||||
name = dis.readUTF();
|
||||
}
|
||||
tags.add(stt.readFrom(name, dis));
|
||||
} while (stt != Type.TAG_End);
|
||||
|
||||
return tags.toArray(new Tag[tags.size()]);
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
for (Tag subTag : value) {
|
||||
dos.writeByte(type.ordinal());
|
||||
if (subTag.type != Type.TAG_End) {
|
||||
dos.writeUTF(subTag.name);
|
||||
subTag.writePayload(dos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a tag to a TAG_Compound.
|
||||
*
|
||||
* We need to add the tag BEFORE the end, or the new tag gets placed after the TAG_End, messing up the data.
|
||||
* TAG_End MUST be kept at the very end of the TAG_Compound.
|
||||
*/
|
||||
public void addTag(Tag tag) {
|
||||
insertTag(tag, value.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first nested tag with specified name in a TAG_Compound.
|
||||
*
|
||||
* @param name the name to look for. May be null to look for unnamed tags.
|
||||
* @return the first nested tag that has the specified name.
|
||||
*/
|
||||
public Tag findTagByName(String name) {
|
||||
return findNextTagByName(name, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
void serialize(PrintStream ps, int indent) {
|
||||
serializePrefix(ps, indent, ": ", value.length - 1, " entries");
|
||||
serializeEntries(ps, indent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagDouble extends Tag<Double> {
|
||||
TagDouble(String name, double value) {
|
||||
super(Type.TAG_Double, name, value);
|
||||
}
|
||||
|
||||
TagDouble(String name, DataInputStream dis) throws IOException {
|
||||
this(name, dis.readDouble());
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeDouble(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagEnd extends Tag<Object> {
|
||||
public TagEnd(String name) {
|
||||
super(Type.TAG_End, name, null);
|
||||
}
|
||||
|
||||
TagEnd(String name, DataInputStream dis) throws IOException {
|
||||
this(name);
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {}
|
||||
|
||||
@Override
|
||||
public void setValue(Object newValue) {
|
||||
if (value != null)
|
||||
throw new IllegalArgumentException();
|
||||
value = newValue;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagFloat extends Tag<Float> {
|
||||
TagFloat(String name, float value) {
|
||||
super(Type.TAG_Float, name, value);
|
||||
}
|
||||
|
||||
TagFloat(String name, DataInputStream dis) throws IOException {
|
||||
this(name, dis.readFloat());
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeFloat(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagInt extends Tag<Integer> {
|
||||
TagInt(String name, int value) {
|
||||
super(Type.TAG_Int, name, value);
|
||||
}
|
||||
|
||||
TagInt(String name, DataInputStream dis) throws IOException {
|
||||
this(name, dis.readInt());
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeInt(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class TagIntArray extends Tag<int[]> {
|
||||
TagIntArray(String name, int[] value) {
|
||||
super(Type.TAG_Int_Array, name, value);
|
||||
}
|
||||
|
||||
TagIntArray(String name, DataInputStream dis) throws IOException {
|
||||
this(name, readPayload(dis));
|
||||
}
|
||||
|
||||
private static int[] readPayload(DataInputStream dis) throws IOException {
|
||||
int length = dis.readInt();
|
||||
int[] ia = new int[length];
|
||||
for (int i=0; i<length; i++)
|
||||
ia[i] = dis.readInt();
|
||||
return ia;
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeInt(value.length);
|
||||
for (int v : value)
|
||||
dos.writeInt(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
void serialize(PrintStream ps, int indent) {
|
||||
serializePrefix(ps, indent, ": [", value.length, " integers]");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
public class TagList<T> extends SequenceTagBase<T> {
|
||||
Type listType;
|
||||
|
||||
/** Create a new TAG_List NBT tag.
|
||||
*
|
||||
* @param name name for the new tag or null to create an unnamed tag.
|
||||
* @param value list of tags to add to the new tag.
|
||||
*/
|
||||
public TagList(String name, Tag<T>[] value) {
|
||||
super(Type.TAG_List, name, value);
|
||||
this.listType = value[0].type;
|
||||
}
|
||||
|
||||
/** Create a new TAG_List with an empty list. Use {@link TagList#addTag(Tag)} to add tags later.
|
||||
*
|
||||
* @param name name for this tag or null to create an unnamed tag.
|
||||
* @param listType type of the elements in this empty list.
|
||||
*/
|
||||
public TagList(String name, Type listType) {
|
||||
super(Type.TAG_List, name, new Tag[0]);
|
||||
this.listType = listType;
|
||||
}
|
||||
|
||||
TagList(String name, DataInputStream dis) throws IOException {
|
||||
super(Type.TAG_List, name, new Tag[0]);
|
||||
Object payload = readPayload(dis);
|
||||
if (payload instanceof Type) {
|
||||
listType = (Type) payload;
|
||||
} else {
|
||||
value = (Tag<T>[]) payload;
|
||||
listType = value[0].type;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Object readPayload(DataInputStream dis) throws IOException {
|
||||
Type type = Type.fromByte(dis.readByte());
|
||||
Tag<T>[] lo = new Tag[dis.readInt()];
|
||||
for (int i = 0; i < lo.length; i++)
|
||||
lo[i] = type.readFrom(null, dis);
|
||||
if (lo.length == 0)
|
||||
return type;
|
||||
else
|
||||
return lo;
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeByte(this.listType.ordinal());
|
||||
dos.writeInt(value.length);
|
||||
for (Tag tag : value)
|
||||
tag.writePayload(dos);
|
||||
}
|
||||
|
||||
/** Add a tag to a TAG_List
|
||||
*/
|
||||
public void addTag(Tag tag) {
|
||||
insertTag(tag, value.length);
|
||||
}
|
||||
|
||||
/** Additional setValue method for empty lists
|
||||
* @param listType
|
||||
*/
|
||||
public void setValue(Type listType) {
|
||||
value = new Tag[0];
|
||||
this.listType = listType;
|
||||
}
|
||||
|
||||
@Override
|
||||
void serialize(PrintStream ps, int indent) {
|
||||
serializePrefix(ps, indent, ": ", value.length, " entries of type ", listType);
|
||||
serializeEntries(ps, indent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagLong extends Tag<Long> {
|
||||
TagLong(String name, long value) {
|
||||
super(Type.TAG_Long, name, value);
|
||||
}
|
||||
|
||||
TagLong(String name, DataInputStream dis) throws IOException {
|
||||
this(name, dis.readLong());
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeLong(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagShort extends Tag<Short> {
|
||||
TagShort(String name, short value) {
|
||||
super(Type.TAG_Short, name, value);
|
||||
}
|
||||
|
||||
TagShort(String name, DataInputStream dis) throws IOException {
|
||||
this(name, dis.readShort());
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeShort(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package amidst.nbt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TagString extends Tag<String> {
|
||||
TagString(String name, String value) {
|
||||
super(Type.TAG_String, name, value);
|
||||
}
|
||||
|
||||
TagString(String name, DataInputStream dis) throws IOException {
|
||||
this(name, dis.readUTF());
|
||||
}
|
||||
|
||||
void writePayload(DataOutputStream dos) throws IOException {
|
||||
dos.writeUTF(value);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,12 @@ import org.junit.Assert;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static amidst.nbt.Tag.Type.*;
|
||||
|
||||
/** Tests NBT Tag class.
|
||||
|
@ -33,4 +39,40 @@ public class TagTest extends Assert {
|
|||
assertEquals(TAG_Compound, types[10]);
|
||||
assertEquals(TAG_Int_Array, types[11]);
|
||||
}
|
||||
|
||||
//testRead covers this implicitly
|
||||
/* Every Tag subclass has to have a constructor with the interface
|
||||
* (String, DataInputStream) throws IOException
|
||||
@Test
|
||||
public void testConstructors() {
|
||||
|
||||
}*/
|
||||
|
||||
/** Reads bigtest.nbt from wiki.vg
|
||||
*/
|
||||
@Test
|
||||
public void testRead() throws IOException {
|
||||
testReadImpl();
|
||||
}
|
||||
|
||||
private TagCompound testReadImpl() throws IOException {
|
||||
return Tag.readFrom(TagTest.class.getResourceAsStream("bigtest.nbt"));
|
||||
}
|
||||
|
||||
/** Tests correctness of serialization
|
||||
*/
|
||||
@Test
|
||||
public void testSerialization() throws IOException {
|
||||
TagCompound bigTest = testReadImpl();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintStream ps = new PrintStream(baos);
|
||||
bigTest.serialize(ps, 0);
|
||||
String serialized = baos.toString();
|
||||
|
||||
InputStream reference = TagTest.class.getResourceAsStream("bigtest.nbt.txt");
|
||||
Scanner s = new Scanner(reference).useDelimiter("\\A");
|
||||
String expected = s.next();
|
||||
|
||||
assertEquals(expected, serialized);
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,45 @@
|
|||
TAG_Compound("Level"): 11 entries
|
||||
{
|
||||
TAG_Long("longTest"): 9223372036854775807
|
||||
TAG_Short("shortTest"): 32767
|
||||
TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING ÅÄÖ!
|
||||
TAG_Float("floatTest"): 0.49823147
|
||||
TAG_Int("intTest"): 2147483647
|
||||
TAG_Compound("nested compound test"): 2 entries
|
||||
{
|
||||
TAG_Compound("ham"): 2 entries
|
||||
{
|
||||
TAG_String("name"): Hampus
|
||||
TAG_Float("value"): 0.75
|
||||
}
|
||||
TAG_Compound("egg"): 2 entries
|
||||
{
|
||||
TAG_String("name"): Eggbert
|
||||
TAG_Float("value"): 0.5
|
||||
}
|
||||
}
|
||||
TAG_List("listTest (long)"): 5 entries of type TAG_Long
|
||||
{
|
||||
TAG_Long: 11
|
||||
TAG_Long: 12
|
||||
TAG_Long: 13
|
||||
TAG_Long: 14
|
||||
TAG_Long: 15
|
||||
}
|
||||
TAG_List("listTest (compound)"): 2 entries of type TAG_Compound
|
||||
{
|
||||
TAG_Compound: 2 entries
|
||||
{
|
||||
TAG_String("name"): Compound tag #0
|
||||
TAG_Long("created-on"): 1264099775885
|
||||
}
|
||||
TAG_Compound: 2 entries
|
||||
{
|
||||
TAG_String("name"): Compound tag #1
|
||||
TAG_Long("created-on"): 1264099775885
|
||||
}
|
||||
}
|
||||
TAG_Byte("byteTest"): 127
|
||||
TAG_Byte_Array("byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))"): [1000 bytes]
|
||||
TAG_Double("doubleTest"): 0.4931287132182315
|
||||
}
|
Loading…
Reference in New Issue