2011-04-06 04:43:54 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.IO.Compression;
|
|
|
|
|
|
2011-04-06 21:20:35 +00:00
|
|
|
|
namespace Substrate.NBT
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
2011-04-06 22:01:22 +00:00
|
|
|
|
using Substrate.Utility;
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
public interface INBTObject<T>
|
|
|
|
|
{
|
2011-04-09 02:50:42 +00:00
|
|
|
|
T LoadTree (TagValue tree);
|
|
|
|
|
T LoadTreeSafe (TagValue tree);
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagValue BuildTree ();
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
bool ValidateTree (TagValue tree);
|
2011-04-06 04:43:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class NBT_Tree : ICopyable<NBT_Tree>
|
|
|
|
|
{
|
|
|
|
|
private Stream _stream = null;
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagCompound _root = null;
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private static TagNull _nulltag = new TagNull();
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
public TagCompound Root
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
get { return _root; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public NBT_Tree ()
|
|
|
|
|
{
|
2011-04-09 02:50:42 +00:00
|
|
|
|
_root = new TagCompound();
|
2011-04-06 04:43:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
public NBT_Tree (TagCompound tree)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
_root = tree;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public NBT_Tree (Stream s)
|
|
|
|
|
{
|
|
|
|
|
ReadFrom(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ReadFrom (Stream s)
|
|
|
|
|
{
|
|
|
|
|
if (s != null) {
|
|
|
|
|
_stream = s;
|
|
|
|
|
_root = ReadRoot();
|
|
|
|
|
_stream = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WriteTo (Stream s)
|
|
|
|
|
{
|
|
|
|
|
if (s != null) {
|
|
|
|
|
_stream = s;
|
|
|
|
|
|
|
|
|
|
if (_root != null) {
|
|
|
|
|
WriteTag("", _root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadValue (TagType type)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_END:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return null;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_BYTE:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadByte();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_SHORT:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadShort();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_INT:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadInt();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_LONG:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadLong();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_FLOAT:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadFloat();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_DOUBLE:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadDouble();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_BYTE_ARRAY:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadByteArray();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_STRING:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadString();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_LIST:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadList();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_COMPOUND:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
return ReadCompound();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new Exception();
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadByte ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
int gzByte = _stream.ReadByte();
|
|
|
|
|
if (gzByte == -1) {
|
|
|
|
|
throw new NBTException(NBTException.MSG_GZIP_ENDOFSTREAM);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagByte val = new TagByte((byte)gzByte);
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadShort ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = new byte[2];
|
|
|
|
|
_stream.Read(gzBytes, 0, 2);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagShort val = new TagShort(BitConverter.ToInt16(gzBytes, 0));
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadInt ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = new byte[4];
|
|
|
|
|
_stream.Read(gzBytes, 0, 4);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagInt val = new TagInt(BitConverter.ToInt32(gzBytes, 0));
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadLong ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = new byte[8];
|
|
|
|
|
_stream.Read(gzBytes, 0, 8);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagLong val = new TagLong(BitConverter.ToInt64(gzBytes, 0));
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadFloat ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = new byte[4];
|
|
|
|
|
_stream.Read(gzBytes, 0, 4);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagFloat val = new TagFloat(BitConverter.ToSingle(gzBytes, 0));
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadDouble ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = new byte[8];
|
|
|
|
|
_stream.Read(gzBytes, 0, 8);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagDouble val = new TagDouble(BitConverter.ToDouble(gzBytes, 0));
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadByteArray ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] lenBytes = new byte[4];
|
|
|
|
|
_stream.Read(lenBytes, 0, 4);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(lenBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int length = BitConverter.ToInt32(lenBytes, 0);
|
|
|
|
|
if (length < 0) {
|
|
|
|
|
throw new NBTException(NBTException.MSG_READ_NEG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] data = new byte[length];
|
|
|
|
|
_stream.Read(data, 0, length);
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagByteArray val = new TagByteArray(data);
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadString ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] lenBytes = new byte[2];
|
|
|
|
|
_stream.Read(lenBytes, 0, 2);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(lenBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
short len = BitConverter.ToInt16(lenBytes, 0);
|
|
|
|
|
if (len < 0) {
|
|
|
|
|
throw new NBTException(NBTException.MSG_READ_NEG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] strBytes = new byte[len];
|
|
|
|
|
_stream.Read(strBytes, 0, len);
|
|
|
|
|
|
|
|
|
|
System.Text.Encoding str = Encoding.GetEncoding(28591);
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagString val = new TagString(str.GetString(strBytes));
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadList ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
int gzByte = _stream.ReadByte();
|
|
|
|
|
if (gzByte == -1) {
|
|
|
|
|
throw new NBTException(NBTException.MSG_GZIP_ENDOFSTREAM);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagList val = new TagList((TagType)gzByte);
|
|
|
|
|
if (val.ValueType > (TagType)Enum.GetValues(typeof(TagType)).GetUpperBound(0)) {
|
2011-04-06 04:43:54 +00:00
|
|
|
|
throw new NBTException(NBTException.MSG_READ_TYPE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] lenBytes = new byte[4];
|
|
|
|
|
_stream.Read(lenBytes, 0, 4);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(lenBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int length = BitConverter.ToInt32(lenBytes, 0);
|
|
|
|
|
if (length < 0) {
|
|
|
|
|
throw new NBTException(NBTException.MSG_READ_NEG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
|
val.Add(ReadValue(val.ValueType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagValue ReadCompound ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagCompound val = new TagCompound();
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
while (ReadTag(val)) ;
|
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private TagCompound ReadRoot ()
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagType type = (TagType)_stream.ReadByte();
|
|
|
|
|
if (type == TagType.TAG_COMPOUND) {
|
|
|
|
|
string name = ReadString().ToTagString().Data;
|
|
|
|
|
return ReadValue(type) as TagCompound;
|
2011-04-06 04:43:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private bool ReadTag (TagCompound parent)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
//NBT_Tag tag = new NBT_Tag();
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
TagType type = (TagType)_stream.ReadByte();
|
|
|
|
|
if (type != TagType.TAG_END) {
|
|
|
|
|
string name = ReadString().ToTagString().Data;
|
2011-04-06 04:43:54 +00:00
|
|
|
|
parent[name] = ReadValue(type);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//tag.Value = ReadValue(type);
|
|
|
|
|
|
|
|
|
|
//return tag;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteValue (TagValue val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
2011-04-09 02:50:42 +00:00
|
|
|
|
switch (val.GetTagType()) {
|
|
|
|
|
case TagType.TAG_END:
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_BYTE:
|
|
|
|
|
WriteByte(val.ToTagByte());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_SHORT:
|
|
|
|
|
WriteShort(val.ToTagShort());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_INT:
|
|
|
|
|
WriteInt(val.ToTagInt());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_LONG:
|
|
|
|
|
WriteLong(val.ToTagLong());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_FLOAT:
|
|
|
|
|
WriteFloat(val.ToTagFloat());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_DOUBLE:
|
|
|
|
|
WriteDouble(val.ToTagDouble());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_BYTE_ARRAY:
|
|
|
|
|
WriteByteArray(val.ToTagByteArray());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_STRING:
|
|
|
|
|
WriteString(val.ToTagString());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_LIST:
|
|
|
|
|
WriteList(val.ToTagList());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
case TagType.TAG_COMPOUND:
|
|
|
|
|
WriteCompound(val.ToTagCompound());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteByte (TagByte val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
_stream.WriteByte(val.Data);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteShort (TagShort val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = BitConverter.GetBytes(val.Data);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.Write(gzBytes, 0, 2);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteInt (TagInt val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = BitConverter.GetBytes(val.Data);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.Write(gzBytes, 0, 4);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteLong (TagLong val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = BitConverter.GetBytes(val.Data);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.Write(gzBytes, 0, 8);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteFloat (TagFloat val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = BitConverter.GetBytes(val.Data);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.Write(gzBytes, 0, 4);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteDouble (TagDouble val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] gzBytes = BitConverter.GetBytes(val.Data);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(gzBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.Write(gzBytes, 0, 8);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteByteArray (TagByteArray val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] lenBytes = BitConverter.GetBytes(val.Length);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(lenBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.Write(lenBytes, 0, 4);
|
|
|
|
|
_stream.Write(val.Data, 0, val.Length);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteString (TagString val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] lenBytes = BitConverter.GetBytes((short)val.Length);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(lenBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.Write(lenBytes, 0, 2);
|
|
|
|
|
|
|
|
|
|
System.Text.Encoding str = Encoding.GetEncoding(28591);
|
|
|
|
|
byte[] gzBytes = str.GetBytes(val.Data);
|
|
|
|
|
|
|
|
|
|
_stream.Write(gzBytes, 0, gzBytes.Length);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteList (TagList val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] lenBytes = BitConverter.GetBytes(val.Count);
|
|
|
|
|
|
|
|
|
|
if (BitConverter.IsLittleEndian) {
|
|
|
|
|
Array.Reverse(lenBytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_stream.WriteByte((byte)val.ValueType);
|
|
|
|
|
_stream.Write(lenBytes, 0, 4);
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
foreach (TagValue v in val) {
|
2011-04-06 04:43:54 +00:00
|
|
|
|
WriteValue(v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteCompound (TagCompound val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
2011-04-09 02:50:42 +00:00
|
|
|
|
foreach (KeyValuePair<string, TagValue> item in val) {
|
2011-04-06 04:43:54 +00:00
|
|
|
|
WriteTag(item.Key, item.Value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WriteTag(null, _nulltag);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
private void WriteTag (string name, TagValue val)
|
2011-04-06 04:43:54 +00:00
|
|
|
|
{
|
2011-04-09 02:50:42 +00:00
|
|
|
|
_stream.WriteByte((byte)val.GetTagType());
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
2011-04-09 02:50:42 +00:00
|
|
|
|
if (val.GetTagType() != TagType.TAG_END) {
|
2011-04-06 04:43:54 +00:00
|
|
|
|
WriteString(name);
|
|
|
|
|
WriteValue(val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region ICopyable<NBT_Tree> Members
|
|
|
|
|
|
|
|
|
|
public NBT_Tree Copy ()
|
|
|
|
|
{
|
|
|
|
|
NBT_Tree tree = new NBT_Tree();
|
2011-04-09 02:50:42 +00:00
|
|
|
|
tree._root = _root.Copy() as TagCompound;
|
2011-04-06 04:43:54 +00:00
|
|
|
|
|
|
|
|
|
return tree;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class NBTException : Exception
|
|
|
|
|
{
|
|
|
|
|
public const String MSG_GZIP_ENDOFSTREAM = "Gzip Error: Unexpected end of stream";
|
|
|
|
|
|
|
|
|
|
public const String MSG_READ_NEG = "Read Error: Negative length";
|
|
|
|
|
public const String MSG_READ_TYPE = "Read Error: Invalid value type";
|
|
|
|
|
|
|
|
|
|
public NBTException () { }
|
|
|
|
|
|
|
|
|
|
public NBTException (String msg) : base(msg) { }
|
|
|
|
|
|
|
|
|
|
public NBTException (String msg, Exception innerException) : base(msg, innerException) { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class InvalidNBTObjectException : Exception { }
|
|
|
|
|
|
|
|
|
|
public class InvalidTagException : Exception { }
|
|
|
|
|
|
|
|
|
|
public class InvalidValueException : Exception { }
|
|
|
|
|
}
|