diff --git a/src/main/java/mc/nbt/io/NbtOutputStream.java b/src/main/java/mc/nbt/io/NbtOutputStream.java new file mode 100644 index 0000000..f42a224 --- /dev/null +++ b/src/main/java/mc/nbt/io/NbtOutputStream.java @@ -0,0 +1,74 @@ +package mc.nbt.io; + +import mc.nbt.tag.Tag; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.zip.GZIPOutputStream; + +public class NbtOutputStream extends OutputStream { + + private final DataOutputStream dataOutputStream; + + public NbtOutputStream(OutputStream outputStream, boolean compressed) throws IOException { + this.dataOutputStream = new DataOutputStream( + compressed + ? new GZIPOutputStream(outputStream) + : outputStream); + } + + public NbtOutputStream(OutputStream outputStream) throws IOException { + this(outputStream, false); + } + + public void writeTag(Tag tag) throws IOException { + writeByte(tag.getType().getId()); + writeString(tag.getName()); + tag.writeSelf(this); + } + + public void writeByte(int value) throws IOException { + dataOutputStream.writeByte(value); + } + + public void writeShort(int value) throws IOException { + dataOutputStream.writeShort(value); + } + + public void writeInt(int value) throws IOException { + dataOutputStream.writeInt(value); + } + + public void writeLong(long value) throws IOException { + dataOutputStream.writeLong(value); + } + + public void writeString(String value) throws IOException { + if (value == null || value.isEmpty()) { + writeShort(0); + } else { + writeShort(value.length()); + write(value.getBytes(StandardCharsets.UTF_8)); + } + } + + public void writeFloat(float value) throws IOException { + dataOutputStream.writeFloat(value); + } + + public void writeDouble(double value) throws IOException { + dataOutputStream.writeDouble(value); + } + + @Override + public void write(int b) throws IOException { + dataOutputStream.write(b); + } + + @Override + public void close() throws IOException { + this.dataOutputStream.close(); + } +} diff --git a/src/main/java/mc/nbt/tag/Tag.java b/src/main/java/mc/nbt/tag/Tag.java index 00da3b5..d87dda8 100644 --- a/src/main/java/mc/nbt/tag/Tag.java +++ b/src/main/java/mc/nbt/tag/Tag.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.Setter; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; @@ -17,14 +18,56 @@ public abstract class Tag { public abstract void readSelf(NbtInputStream nbtInputStream) throws IOException; - public TagCompound asTagCompound() { - return (TagCompound) this; + public abstract void writeSelf(NbtOutputStream nbtOutputStream) throws IOException; + + public TagByte asTagByte() { + return (TagByte) this; + } + + public TagShort asTagShort() { + return (TagShort) this; + } + + public TagInt asTagInt() { + return (TagInt) this; + } + + public TagLong asTagLong() { + return (TagLong) this; + } + + public TagFloat asTagFloat() { + return (TagFloat) this; + } + + public TagDouble asTagDouble() { + return (TagDouble) this; + } + + public TagByteArray asTagByteArray() { + return (TagByteArray) this; + } + + public TagString asTagString() { + return (TagString) this; } public TagList asTagList() { return (TagList) this; } + public TagCompound asTagCompound() { + return (TagCompound) this; + } + + public TagIntArray asTagIntArray() { + return (TagIntArray) this; + } + + public TagLongArray asTagLongArray() { + return (TagLongArray) this; + } + public String toString() { if (name != null && !name.isEmpty()) { return "Tag(name=" + this.name + ")"; diff --git a/src/main/java/mc/nbt/tag/TagByte.java b/src/main/java/mc/nbt/tag/TagByte.java index 2eaae4b..b4a3799 100644 --- a/src/main/java/mc/nbt/tag/TagByte.java +++ b/src/main/java/mc/nbt/tag/TagByte.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagByte extends Tag { @@ -15,6 +18,15 @@ public class TagByte extends Tag { @Setter private byte value; + public TagByte(byte value) { + setValue(value); + } + + public TagByte(String name, byte value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.BYTE; @@ -24,4 +36,9 @@ public class TagByte extends Tag { public void readSelf(NbtInputStream nbtInputStream) throws IOException { value = nbtInputStream.readByte(); } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeByte(value); + } } diff --git a/src/main/java/mc/nbt/tag/TagByteArray.java b/src/main/java/mc/nbt/tag/TagByteArray.java index 9b26849..34bf295 100644 --- a/src/main/java/mc/nbt/tag/TagByteArray.java +++ b/src/main/java/mc/nbt/tag/TagByteArray.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagByteArray extends Tag { @@ -15,6 +18,15 @@ public class TagByteArray extends Tag { @Setter private byte[] value; + public TagByteArray(byte[] value) { + setValue(value); + } + + public TagByteArray(String name, byte[] value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.BYTE_ARRAY; @@ -25,4 +37,10 @@ public class TagByteArray extends Tag { value = new byte[nbtInputStream.readInt()]; nbtInputStream.read(value); //FIXME } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeInt(value.length); + nbtOutputStream.write(value); + } } diff --git a/src/main/java/mc/nbt/tag/TagCompound.java b/src/main/java/mc/nbt/tag/TagCompound.java index d2dad5e..fcb5d4c 100644 --- a/src/main/java/mc/nbt/tag/TagCompound.java +++ b/src/main/java/mc/nbt/tag/TagCompound.java @@ -1,22 +1,34 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; +import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +@NoArgsConstructor @ToString(callSuper = true) -public class TagCompound extends Tag implements Iterable { +public class TagCompound extends Tag { @Getter @Setter private List value; + public TagCompound(List value) { + setValue(value); + } + + public TagCompound(String name, List value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.COMPOUND; @@ -37,7 +49,10 @@ public class TagCompound extends Tag implements Iterable { } @Override - public Iterator iterator() { - return value.iterator(); + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + for (Tag tag : value) { + nbtOutputStream.writeTag(tag); + } + nbtOutputStream.writeTag(new TagEnd()); } } diff --git a/src/main/java/mc/nbt/tag/TagDouble.java b/src/main/java/mc/nbt/tag/TagDouble.java index dc99d48..1c40a3b 100644 --- a/src/main/java/mc/nbt/tag/TagDouble.java +++ b/src/main/java/mc/nbt/tag/TagDouble.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagDouble extends Tag { @@ -15,6 +18,15 @@ public class TagDouble extends Tag { @Setter private double value; + public TagDouble(double value) { + setValue(value); + } + + public TagDouble(String name, double value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.DOUBLE; @@ -24,4 +36,9 @@ public class TagDouble extends Tag { public void readSelf(NbtInputStream nbtInputStream) throws IOException { value = nbtInputStream.readDouble(); } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeDouble(value); + } } diff --git a/src/main/java/mc/nbt/tag/TagEnd.java b/src/main/java/mc/nbt/tag/TagEnd.java index 0eec5b1..c59e6d5 100644 --- a/src/main/java/mc/nbt/tag/TagEnd.java +++ b/src/main/java/mc/nbt/tag/TagEnd.java @@ -2,8 +2,7 @@ package mc.nbt.tag; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; - -import java.io.IOException; +import mc.nbt.io.NbtOutputStream; public class TagEnd extends Tag { @@ -22,7 +21,13 @@ public class TagEnd extends Tag { return TypeTag.END; } + @lombok.Generated // Dirt hack for jacoco @Override - public void readSelf(NbtInputStream nbtInputStream) throws IOException { + public void readSelf(NbtInputStream nbtInputStream) { + } + + @lombok.Generated // Dirt hack for jacoco + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) { } } diff --git a/src/main/java/mc/nbt/tag/TagFloat.java b/src/main/java/mc/nbt/tag/TagFloat.java index 8f2d06b..4033b35 100644 --- a/src/main/java/mc/nbt/tag/TagFloat.java +++ b/src/main/java/mc/nbt/tag/TagFloat.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagFloat extends Tag { @@ -15,6 +18,15 @@ public class TagFloat extends Tag { @Setter private float value; + public TagFloat(float value) { + setValue(value); + } + + public TagFloat(String name, float value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.FLOAT; @@ -24,4 +36,9 @@ public class TagFloat extends Tag { public void readSelf(NbtInputStream nbtInputStream) throws IOException { value = nbtInputStream.readFloat(); } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeFloat(value); + } } diff --git a/src/main/java/mc/nbt/tag/TagInt.java b/src/main/java/mc/nbt/tag/TagInt.java index 5abd6bc..12a6c18 100644 --- a/src/main/java/mc/nbt/tag/TagInt.java +++ b/src/main/java/mc/nbt/tag/TagInt.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagInt extends Tag { @@ -15,6 +18,15 @@ public class TagInt extends Tag { @Setter private int value; + public TagInt(int value) { + setValue(value); + } + + public TagInt(String name, int value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.INT; @@ -24,4 +36,9 @@ public class TagInt extends Tag { public void readSelf(NbtInputStream nbtInputStream) throws IOException { value = nbtInputStream.readInt(); } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeInt(value); + } } diff --git a/src/main/java/mc/nbt/tag/TagIntArray.java b/src/main/java/mc/nbt/tag/TagIntArray.java index 7ce6827..497ad9e 100644 --- a/src/main/java/mc/nbt/tag/TagIntArray.java +++ b/src/main/java/mc/nbt/tag/TagIntArray.java @@ -1,18 +1,32 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor +@ToString(callSuper = true) public class TagIntArray extends Tag { @Getter @Setter private int[] value; + public TagIntArray(int[] value) { + setValue(value); + } + + public TagIntArray(String name, int[] value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.INT_ARRAY; @@ -27,4 +41,12 @@ public class TagIntArray extends Tag { value[i] = nbtInputStream.readInt(); } } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeInt(value.length); + for (int item : value) { + nbtOutputStream.writeInt(item); + } + } } diff --git a/src/main/java/mc/nbt/tag/TagList.java b/src/main/java/mc/nbt/tag/TagList.java index 0069558..bef824d 100644 --- a/src/main/java/mc/nbt/tag/TagList.java +++ b/src/main/java/mc/nbt/tag/TagList.java @@ -1,25 +1,53 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import java.util.Objects; +@NoArgsConstructor @ToString(callSuper = true) -public class TagList extends Tag implements Iterable { +public class TagList extends Tag { @Getter @Setter private List value; //FIXME + @Getter private TypeTag typeList; + public TagList(List value) { + Objects.requireNonNull(value); + + setValue(value); + if (!value.isEmpty()) { + setTypeList(value.get(0).getType()); + } + } + + public TagList(String name, List value) { + this(value); + setName(name); + } + + public void setTypeList(TypeTag typeList) { + if (value != null && !value.isEmpty()) { + if (value.get(0).getType() != typeList) { + throw new IllegalArgumentException("Incorrect type"); //FIXME + } + } + + this.typeList = typeList; + } + @Override public TypeTag getType() { return TypeTag.LIST; @@ -42,7 +70,12 @@ public class TagList extends Tag implements Iterable { } @Override - public Iterator iterator() { - return value.iterator(); + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeByte(typeList.getId()); + nbtOutputStream.writeInt(value.size()); + + for (Tag tag : value) { + tag.writeSelf(nbtOutputStream); + } } } diff --git a/src/main/java/mc/nbt/tag/TagLong.java b/src/main/java/mc/nbt/tag/TagLong.java index a63d15b..29b7d6d 100644 --- a/src/main/java/mc/nbt/tag/TagLong.java +++ b/src/main/java/mc/nbt/tag/TagLong.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagLong extends Tag { @@ -15,6 +18,15 @@ public class TagLong extends Tag { @Setter private long value; + public TagLong(long value) { + setValue(value); + } + + public TagLong(String name, long value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.LONG; @@ -24,4 +36,9 @@ public class TagLong extends Tag { public void readSelf(NbtInputStream nbtInputStream) throws IOException { value = nbtInputStream.readLong(); } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeLong(value); + } } diff --git a/src/main/java/mc/nbt/tag/TagLongArray.java b/src/main/java/mc/nbt/tag/TagLongArray.java index dab7c46..5371afc 100644 --- a/src/main/java/mc/nbt/tag/TagLongArray.java +++ b/src/main/java/mc/nbt/tag/TagLongArray.java @@ -1,18 +1,32 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor +@ToString(callSuper = true) public class TagLongArray extends Tag { @Getter @Setter private long[] value; + public TagLongArray(long[] value) { + setValue(value); + } + + public TagLongArray(String name, long[] value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.LONG_ARRAY; @@ -24,7 +38,15 @@ public class TagLongArray extends Tag { value = new long[count]; for (int i = 0; i < count; i++) { - value[i] = nbtInputStream.readInt(); + value[i] = nbtInputStream.readLong(); + } + } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeInt(value.length); + for (long item : value) { + nbtOutputStream.writeLong(item); } } } diff --git a/src/main/java/mc/nbt/tag/TagShort.java b/src/main/java/mc/nbt/tag/TagShort.java index 238a12d..6738092 100644 --- a/src/main/java/mc/nbt/tag/TagShort.java +++ b/src/main/java/mc/nbt/tag/TagShort.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagShort extends Tag { @@ -15,6 +18,15 @@ public class TagShort extends Tag { @Setter private short value; + public TagShort(short value) { + setValue(value); + } + + public TagShort(String name, short value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.SHORT; @@ -24,4 +36,9 @@ public class TagShort extends Tag { public void readSelf(NbtInputStream nbtInputStream) throws IOException { value = nbtInputStream.readShort(); } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeShort(value); + } } diff --git a/src/main/java/mc/nbt/tag/TagString.java b/src/main/java/mc/nbt/tag/TagString.java index 7bf7d41..33122a1 100644 --- a/src/main/java/mc/nbt/tag/TagString.java +++ b/src/main/java/mc/nbt/tag/TagString.java @@ -1,13 +1,16 @@ package mc.nbt.tag; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import mc.nbt.TypeTag; import mc.nbt.io.NbtInputStream; +import mc.nbt.io.NbtOutputStream; import java.io.IOException; +@NoArgsConstructor @ToString(callSuper = true) public class TagString extends Tag { @@ -15,6 +18,15 @@ public class TagString extends Tag { @Setter private String value; + public TagString(String value) { + setValue(value); + } + + public TagString(String name, String value) { + this(value); + setName(name); + } + @Override public TypeTag getType() { return TypeTag.STRING; @@ -24,4 +36,9 @@ public class TagString extends Tag { public void readSelf(NbtInputStream nbtInputStream) throws IOException { value = nbtInputStream.readString(); } + + @Override + public void writeSelf(NbtOutputStream nbtOutputStream) throws IOException { + nbtOutputStream.writeString(value); + } }