From 24774776a2c2de2cdb443f77723bc7f50ad9abc9 Mon Sep 17 00:00:00 2001 From: Justin Aquadro Date: Sat, 2 Apr 2011 00:44:17 +0000 Subject: [PATCH] Missed updates --- NBToolkit/NBToolkit/Map/NBT/NBT.cs | 480 ++++++++++++++++++ NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs | 172 +++++++ NBToolkit/NBToolkit/Map/NBT/NBTValues.cs | 557 +++++++++++++++++++++ NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs | 206 ++++++++ 4 files changed, 1415 insertions(+) create mode 100644 NBToolkit/NBToolkit/Map/NBT/NBT.cs create mode 100644 NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs create mode 100644 NBToolkit/NBToolkit/Map/NBT/NBTValues.cs create mode 100644 NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs diff --git a/NBToolkit/NBToolkit/Map/NBT/NBT.cs b/NBToolkit/NBToolkit/Map/NBT/NBT.cs new file mode 100644 index 0000000..68977a1 --- /dev/null +++ b/NBToolkit/NBToolkit/Map/NBT/NBT.cs @@ -0,0 +1,480 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.IO.Compression; + +namespace NBToolkit.NBT +{ + + public class NBT_Tree + { + private Stream _stream = null; + private NBT_Compound _root = null; + + private static NBT_Null _nulltag = new NBT_Null(); + + public NBT_Compound Root + { + get { return _root; } + } + + public NBT_Tree () + { + _root = new NBT_Compound(); + } + + 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; + } + } + + private NBT_Value ReadValue (NBT_Type type) + { + switch (type) { + case NBT_Type.TAG_END: + return null; + + case NBT_Type.TAG_BYTE: + return ReadByte(); + + case NBT_Type.TAG_SHORT: + return ReadShort(); + + case NBT_Type.TAG_INT: + return ReadInt(); + + case NBT_Type.TAG_LONG: + return ReadLong(); + + case NBT_Type.TAG_FLOAT: + return ReadFloat(); + + case NBT_Type.TAG_DOUBLE: + return ReadDouble(); + + case NBT_Type.TAG_BYTE_ARRAY: + return ReadByteArray(); + + case NBT_Type.TAG_STRING: + return ReadString(); + + case NBT_Type.TAG_LIST: + return ReadList(); + + case NBT_Type.TAG_COMPOUND: + return ReadCompound(); + } + + throw new Exception(); + } + + private NBT_Value ReadByte () + { + int gzByte = _stream.ReadByte(); + if (gzByte == -1) { + throw new NBTException(NBTException.MSG_GZIP_ENDOFSTREAM); + } + + NBT_Byte val = new NBT_Byte((byte)gzByte); + + return val; + } + + private NBT_Value ReadShort () + { + byte[] gzBytes = new byte[2]; + _stream.Read(gzBytes, 0, 2); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + NBT_Short val = new NBT_Short(BitConverter.ToInt16(gzBytes, 0)); + + return val; + } + + private NBT_Value ReadInt () + { + byte[] gzBytes = new byte[4]; + _stream.Read(gzBytes, 0, 4); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + NBT_Int val = new NBT_Int(BitConverter.ToInt32(gzBytes, 0)); + + return val; + } + + private NBT_Value ReadLong () + { + byte[] gzBytes = new byte[8]; + _stream.Read(gzBytes, 0, 8); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + NBT_Long val = new NBT_Long(BitConverter.ToInt64(gzBytes, 0)); + + return val; + } + + private NBT_Value ReadFloat () + { + byte[] gzBytes = new byte[4]; + _stream.Read(gzBytes, 0, 4); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + NBT_Float val = new NBT_Float(BitConverter.ToSingle(gzBytes, 0)); + + return val; + } + + private NBT_Value ReadDouble () + { + byte[] gzBytes = new byte[8]; + _stream.Read(gzBytes, 0, 8); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + NBT_Double val = new NBT_Double(BitConverter.ToDouble(gzBytes, 0)); + + return val; + } + + private NBT_Value ReadByteArray () + { + 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); + + NBT_ByteArray val = new NBT_ByteArray(data); + + return val; + } + + private NBT_Value ReadString () + { + 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); + + NBT_String val = new NBT_String(str.GetString(strBytes)); + + return val; + } + + private NBT_Value ReadList () + { + int gzByte = _stream.ReadByte(); + if (gzByte == -1) { + throw new NBTException(NBTException.MSG_GZIP_ENDOFSTREAM); + } + + NBT_List val = new NBT_List((NBT_Type)gzByte); + if (val.ValueType > (NBT_Type)Enum.GetValues(typeof(NBT_Type)).GetUpperBound(0)) { + 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; + } + + private NBT_Value ReadCompound () + { + NBT_Compound val = new NBT_Compound(); + + while (ReadTag(val)) ; + + return val; + } + + private NBT_Compound ReadRoot () + { + NBT_Type type = (NBT_Type)_stream.ReadByte(); + if (type == NBT_Type.TAG_COMPOUND) { + string name = ReadString().ToNBTString().Data; + return ReadValue(type) as NBT_Compound; + } + + return null; + } + + private bool ReadTag (NBT_Compound parent) + { + //NBT_Tag tag = new NBT_Tag(); + + NBT_Type type = (NBT_Type)_stream.ReadByte(); + if (type != NBT_Type.TAG_END) { + string name = ReadString().ToNBTString().Data; + parent[name] = ReadValue(type); + return true; + } + + return false; + + //tag.Value = ReadValue(type); + + //return tag; + } + + private void WriteValue (NBT_Value val) + { + switch (val.GetNBTType()) { + case NBT_Type.TAG_END: + break; + + case NBT_Type.TAG_BYTE: + WriteByte(val.ToNBTByte()); + break; + + case NBT_Type.TAG_SHORT: + WriteShort(val.ToNBTShort()); + break; + + case NBT_Type.TAG_INT: + WriteInt(val.ToNBTInt()); + break; + + case NBT_Type.TAG_LONG: + WriteLong(val.ToNBTLong()); + break; + + case NBT_Type.TAG_FLOAT: + WriteFloat(val.ToNBTFloat()); + break; + + case NBT_Type.TAG_DOUBLE: + WriteDouble(val.ToNBTDouble()); + break; + + case NBT_Type.TAG_BYTE_ARRAY: + WriteByteArray(val.ToNBTByteArray()); + break; + + case NBT_Type.TAG_STRING: + WriteString(val.ToNBTString()); + break; + + case NBT_Type.TAG_LIST: + WriteList(val.ToNBTList()); + break; + + case NBT_Type.TAG_COMPOUND: + WriteCompound(val.ToNBTCompound()); + break; + } + } + + private void WriteByte (NBT_Byte val) + { + _stream.WriteByte(val.Data); + } + + private void WriteShort (NBT_Short val) + { + byte[] gzBytes = BitConverter.GetBytes(val.Data); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + _stream.Write(gzBytes, 0, 2); + } + + private void WriteInt (NBT_Int val) + { + byte[] gzBytes = BitConverter.GetBytes(val.Data); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + _stream.Write(gzBytes, 0, 4); + } + + private void WriteLong (NBT_Long val) + { + byte[] gzBytes = BitConverter.GetBytes(val.Data); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + _stream.Write(gzBytes, 0, 8); + } + + private void WriteFloat (NBT_Float val) + { + byte[] gzBytes = BitConverter.GetBytes(val.Data); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + _stream.Write(gzBytes, 0, 4); + } + + private void WriteDouble (NBT_Double val) + { + byte[] gzBytes = BitConverter.GetBytes(val.Data); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(gzBytes); + } + + _stream.Write(gzBytes, 0, 8); + } + + private void WriteByteArray (NBT_ByteArray val) + { + byte[] lenBytes = BitConverter.GetBytes(val.Length); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(lenBytes); + } + + _stream.Write(lenBytes, 0, 4); + _stream.Write(val.Data, 0, val.Length); + } + + private void WriteString (NBT_String val) + { + 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); + } + + private void WriteList (NBT_List val) + { + byte[] lenBytes = BitConverter.GetBytes(val.Count); + + if (BitConverter.IsLittleEndian) { + Array.Reverse(lenBytes); + } + + _stream.WriteByte((byte)val.ValueType); + _stream.Write(lenBytes, 0, 4); + + foreach (NBT_Value v in val) { + WriteValue(v); + } + } + + private void WriteCompound (NBT_Compound val) + { + foreach (KeyValuePair item in val) { + WriteTag(item.Key, item.Value); + } + + WriteTag(null, _nulltag); + } + + private void WriteTag (string name, NBT_Value val) + { + _stream.WriteByte((byte)val.GetNBTType()); + + if (val.GetNBTType() != NBT_Type.TAG_END) { + WriteString(name); + WriteValue(val); + } + } + } + + 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 InvalidTagException : Exception { } + + public class InvalidValueException : Exception { } +} diff --git a/NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs b/NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs new file mode 100644 index 0000000..bce0f76 --- /dev/null +++ b/NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.NBT +{ + public abstract class NBTSchemaNode + { + private string _name; + + public string Name + { + get { return _name; } + } + + public NBTSchemaNode (string name) + { + _name = name; + } + } + + public class NBTScalerNode : NBTSchemaNode + { + private NBT_Type _type; + + public NBT_Type Type + { + get { return _type; } + } + + public NBTScalerNode (string name, NBT_Type type) + : base(name) + { + _type = type; + } + } + + public class NBTArrayNode : NBTSchemaNode + { + private int _length; + + public int Length + { + get { return _length; } + } + + public NBTArrayNode (string name) + : base(name) + { + _length = 0; + } + + public NBTArrayNode (string name, int length) + : base(name) + { + _length = length; + } + } + + public class NBTListNode : NBTSchemaNode + { + private NBT_Type _type; + private int _length; + + public int Length + { + get { return _length; } + } + + public NBT_Type Type + { + get { return _type; } + } + + public NBTListNode (string name, NBT_Type type) + : base(name) + { + _type = type; + _length = 0; + } + + public NBTListNode (string name, NBT_Type type, int length) + : base(name) + { + _type = type; + _length = length; + } + } + + public class NBTCompoundNode : NBTSchemaNode, ICollection + { + private List _subnodes; + + #region ICollection Members + + public void Add (NBTSchemaNode item) + { + _subnodes.Add(item); + } + + public void Clear () + { + _subnodes.Clear(); + } + + public bool Contains (NBTSchemaNode item) + { + return _subnodes.Contains(item); + } + + public void CopyTo (NBTSchemaNode[] array, int arrayIndex) + { + _subnodes.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return _subnodes.Count; } + } + + public bool IsReadOnly + { + get { return false; } + } + + public bool Remove (NBTSchemaNode item) + { + return _subnodes.Remove(item); + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator () + { + return _subnodes.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () + { + return _subnodes.GetEnumerator(); + } + + #endregion + + public NBTCompoundNode () + : base("") + { + _subnodes = new List(); + } + + public NBTCompoundNode (string name) + : base(name) + { + _subnodes = new List(); + } + + public NBTCompoundNode MergeInto (NBTCompoundNode tree) + { + foreach (NBTSchemaNode node in _subnodes) { + tree.Add(node); + } + + return tree; + } + } +} diff --git a/NBToolkit/NBToolkit/Map/NBT/NBTValues.cs b/NBToolkit/NBToolkit/Map/NBT/NBTValues.cs new file mode 100644 index 0000000..4fe4cfb --- /dev/null +++ b/NBToolkit/NBToolkit/Map/NBT/NBTValues.cs @@ -0,0 +1,557 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.NBT { + + /// + /// Describes the type of value held by an NBT_Tag + /// + public enum NBT_Type + { + TAG_END = 0, + TAG_BYTE = 1, // 8 bits signed + TAG_SHORT = 2, // 16 bits signed + TAG_INT = 3, // 32 bits signed + TAG_LONG = 4, // 64 bits signed + TAG_FLOAT = 5, + TAG_DOUBLE = 6, + TAG_BYTE_ARRAY = 7, + TAG_STRING = 8, + TAG_LIST = 9, + TAG_COMPOUND = 10 + } + + public abstract class NBT_Value + { + virtual public NBT_Null ToNBTNull () { throw new InvalidCastException(); } + virtual public NBT_Byte ToNBTByte () { throw new InvalidCastException(); } + virtual public NBT_Short ToNBTShort () { throw new InvalidCastException(); } + virtual public NBT_Int ToNBTInt () { throw new InvalidCastException(); } + virtual public NBT_Long ToNBTLong () { throw new InvalidCastException(); } + virtual public NBT_Float ToNBTFloat () { throw new InvalidCastException(); } + virtual public NBT_Double ToNBTDouble () { throw new InvalidCastException(); } + virtual public NBT_ByteArray ToNBTByteArray () { throw new InvalidCastException(); } + virtual public NBT_String ToNBTString () { throw new InvalidCastException(); } + virtual public NBT_List ToNBTList () { throw new InvalidCastException(); } + virtual public NBT_Compound ToNBTCompound () { throw new InvalidCastException(); } + + virtual public NBT_Type GetNBTType () { return NBT_Type.TAG_END; } + } + + public class NBT_Null : NBT_Value + { + override public NBT_Null ToNBTNull () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_END; } + } + + public class NBT_Byte : NBT_Value + { + private byte _data = 0; + + override public NBT_Byte ToNBTByte () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_BYTE; } + + public byte Data + { + get { return _data; } + set { _data = value; } + } + + public NBT_Byte () { } + + public NBT_Byte (byte d) + { + _data = d; + } + + public static implicit operator NBT_Byte (byte b) + { + return new NBT_Byte(b); + } + + public static implicit operator byte (NBT_Byte b) + { + return b._data; + } + } + + public class NBT_Short : NBT_Value + { + private short _data = 0; + + override public NBT_Short ToNBTShort () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_SHORT; } + + public short Data + { + get { return _data; } + set { _data = value; } + } + + public NBT_Short () { } + + public NBT_Short (short d) + { + _data = d; + } + + public static implicit operator NBT_Short (short s) + { + return new NBT_Short(s); + } + + public static implicit operator short (NBT_Short s) + { + return s._data; + } + } + + public class NBT_Int : NBT_Value + { + private int _data = 0; + + override public NBT_Int ToNBTInt () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_INT; } + + public int Data + { + get { return _data; } + set { _data = value; } + } + + public NBT_Int () { } + + public NBT_Int (int d) + { + _data = d; + } + + public static implicit operator NBT_Int (int i) + { + return new NBT_Int(i); + } + + public static implicit operator int (NBT_Int i) + { + return i._data; + } + } + + public class NBT_Long : NBT_Value + { + private long _data = 0; + + override public NBT_Long ToNBTLong () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_LONG; } + + public long Data + { + get { return _data; } + set { _data = value; } + } + + public NBT_Long () { } + + public NBT_Long (long d) + { + _data = d; + } + + public static implicit operator NBT_Long (long l) + { + return new NBT_Long(l); + } + + public static implicit operator long (NBT_Long l) + { + return l._data; + } + } + + public class NBT_Float : NBT_Value + { + private float _data = 0; + + override public NBT_Float ToNBTFloat () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_FLOAT; } + + public float Data + { + get { return _data; } + set { _data = value; } + } + + public NBT_Float () { } + + public NBT_Float (float d) + { + _data = d; + } + + public static implicit operator NBT_Float (float f) + { + return new NBT_Float(f); + } + + public static implicit operator float (NBT_Float f) + { + return f._data; + } + } + + public class NBT_Double : NBT_Value + { + private double _data = 0; + + override public NBT_Double ToNBTDouble () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_DOUBLE; } + + public double Data + { + get { return _data; } + set { _data = value; } + } + + public NBT_Double () { } + + public NBT_Double (double d) + { + _data = d; + } + + public static implicit operator NBT_Double (double d) + { + return new NBT_Double(d); + } + + public static implicit operator double (NBT_Double d) + { + return d._data; + } + } + + public class NBT_ByteArray : NBT_Value + { + private byte[] _data = null; + + override public NBT_ByteArray ToNBTByteArray () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_BYTE_ARRAY; } + + public byte[] Data + { + get { return _data; } + set { _data = value; } + } + + public int Length + { + get { return _data.Length; } + } + + public NBT_ByteArray () { } + + public NBT_ByteArray (byte[] d) + { + _data = d; + } + + public byte this [int index] { + get { return _data[index]; } + set { _data[index] = value; } + } + + public static implicit operator NBT_ByteArray (byte[] b) + { + return new NBT_ByteArray(b); + } + } + + public class NBT_String : NBT_Value + { + private string _data = null; + + override public NBT_String ToNBTString () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_STRING; } + + public string Data + { + get { return _data; } + set { _data = value; } + } + + public int Length + { + get { return _data.Length; } + } + + public NBT_String () { } + + public NBT_String (string d) + { + _data = d; + } + + public static implicit operator NBT_String (string s) + { + return new NBT_String(s); + } + + public static implicit operator string (NBT_String s) + { + return s._data; + } + } + + public class NBT_List : NBT_Value, IList + { + private NBT_Type _type = NBT_Type.TAG_END; + + private List _items = null; + + override public NBT_List ToNBTList () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_LIST; } + + public int Count + { + get { return _items.Count; } + } + + public NBT_Type ValueType + { + get { return _type; } + } + + public NBT_List (NBT_Type type) + { + _type = type; + _items = new List(); + } + + public NBT_List (NBT_Type type, List items) + { + _type = type; + _items = items; + } + + #region IList Members + + public int IndexOf (NBT_Value item) + { + return _items.IndexOf(item); + } + + public void Insert (int index, NBT_Value item) + { + _items.Insert(index, item); + } + + public void RemoveAt (int index) + { + _items.RemoveAt(index); + } + + public NBT_Value this[int index] + { + get + { + return _items[index]; + } + set + { + _items[index] = value; + } + } + + #endregion + + #region ICollection Members + + public void Add (NBT_Value item) + { + _items.Add(item); + } + + public void Clear () + { + _items.Clear(); + } + + public bool Contains (NBT_Value item) + { + return _items.Contains(item); + } + + public void CopyTo (NBT_Value[] array, int arrayIndex) + { + _items.CopyTo(array, arrayIndex); + } + + public bool IsReadOnly + { + get { return false; } + } + + public bool Remove (NBT_Value item) + { + return _items.Remove(item); + } + + #endregion + + #region IEnumerable Members + + public IEnumerator GetEnumerator () + { + return _items.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () + { + return _items.GetEnumerator(); + } + + #endregion + } + + public class NBT_Compound : NBT_Value, IDictionary + { + private Dictionary _tags; + + override public NBT_Compound ToNBTCompound () { return this; } + override public NBT_Type GetNBTType () { return NBT_Type.TAG_COMPOUND; } + + public int Count + { + get { return _tags.Count; } + } + + public NBT_Compound () + { + _tags = new Dictionary(); + } + + #region IDictionary Members + + public void Add (string key, NBT_Value value) + { + _tags.Add(key, value); + } + + public bool ContainsKey (string key) + { + return _tags.ContainsKey(key); + } + + public ICollection Keys + { + get { return _tags.Keys; } + } + + public bool Remove (string key) + { + return _tags.Remove(key); + } + + public bool TryGetValue (string key, out NBT_Value value) + { + return _tags.TryGetValue(key, out value); + } + + public ICollection Values + { + get { return _tags.Values; } + } + + public NBT_Value this[string key] + { + get + { + return _tags[key]; + } + set + { + _tags[key] = value; + } + } + + #endregion + + #region ICollection> Members + + public void Add (KeyValuePair item) + { + _tags.Add(item.Key, item.Value); + } + + public void Clear () + { + _tags.Clear(); + } + + public bool Contains (KeyValuePair item) + { + NBT_Value value; + if (!_tags.TryGetValue(item.Key, out value)) { + return false; + } + return value == item.Value; + } + + public void CopyTo (KeyValuePair[] array, int arrayIndex) + { + if (array == null) { + throw new ArgumentNullException(); + } + if (arrayIndex < 0) { + throw new ArgumentOutOfRangeException(); + } + if (array.Length - arrayIndex < _tags.Count) { + throw new ArgumentException(); + } + + foreach (KeyValuePair item in _tags) { + array[arrayIndex] = item; + arrayIndex++; + } + } + + public bool IsReadOnly + { + get { return false; } + } + + public bool Remove (KeyValuePair item) + { + if (Contains(item)) { + _tags.Remove(item.Key); + return true; + } + return false; + } + + #endregion + + #region IEnumerable> Members + + public IEnumerator> GetEnumerator () + { + return _tags.GetEnumerator(); + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () + { + return _tags.GetEnumerator(); + } + + #endregion + } +} \ No newline at end of file diff --git a/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs b/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs new file mode 100644 index 0000000..3ba8c53 --- /dev/null +++ b/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.NBT +{ + public delegate void MissingTagHandler (Object o, TagEventArgs e); + public delegate void InvalidTagTypeHandler (Object o, TagEventArgs e); + public delegate void InvalidTagValueHandler (Object o, TagEventArgs e); + + public interface INBTVerifier + { + event MissingTagHandler MissingTag; + event InvalidTagTypeHandler InvalidTagType; + event InvalidTagValueHandler InvalidTagValue; + + bool Verify (); + } + + public class TagEventArgs : EventArgs + { + protected string _tagName; + protected NBT_Value _tag; + protected NBTSchemaNode _schema; + + public string TagName + { + get { return _tagName; } + } + + /* public NBT_Tag Tag + { + get { return _tag; } + }*/ + + public TagEventArgs (string tagName) + : base() + { + _tagName = tagName; + } + + public TagEventArgs (string tagName, NBT_Value tag) + : base() + { + _tag = tag; + _tagName = tagName; + } + + public TagEventArgs (NBTSchemaNode schema, NBT_Value tag) + : base() + { + _tag = tag; + _schema = schema; + } + } + + public class NBTVerifier : INBTVerifier + { + private NBT_Compound _root; + private NBTSchemaNode _schema; + + public event MissingTagHandler MissingTag; + public event InvalidTagTypeHandler InvalidTagType; + public event InvalidTagValueHandler InvalidTagValue; + + public NBTVerifier () { } + + public NBTVerifier (NBT_Compound root, NBTSchemaNode schema) + { + _root = root; + _schema = schema; + } + + public bool Verify () + { + return Verify(_root, _schema); + } + + static NBTCompoundNode inventorySchema = new NBTCompoundNode("") + { + new NBTScalerNode("id", NBT_Type.TAG_SHORT), + new NBTScalerNode("Damage", NBT_Type.TAG_SHORT), + new NBTScalerNode("Count", NBT_Type.TAG_BYTE), + new NBTScalerNode("Slot", NBT_Type.TAG_BYTE), + }; + + private bool Verify (NBT_Value tag, NBTSchemaNode schema) + { + if (tag == null) { + OnMissingTag(new TagEventArgs(schema.Name)); + return false; + } + + NBTScalerNode scaler = schema as NBTScalerNode; + if (scaler != null) { + return VerifyScaler(tag, scaler); + } + + NBTArrayNode array = schema as NBTArrayNode; + if (array != null) { + return VerifyArray(tag, array); + } + + NBTListNode list = schema as NBTListNode; + if (list != null) { + return VerifyList(tag, list); + } + + NBTCompoundNode compound = schema as NBTCompoundNode; + if (compound != null) { + return VerifyCompound(tag, compound); + } + + return false; + } + + private bool VerifyScaler (NBT_Value tag, NBTScalerNode schema) + { + if (tag.GetNBTType() != schema.Type) { + OnInvalidTagType(new TagEventArgs(schema.Name, tag)); + return false; + } + + return true; + } + + private bool VerifyArray (NBT_Value tag, NBTArrayNode schema) + { + NBT_ByteArray atag = tag as NBT_ByteArray; + if (atag == null) { + OnInvalidTagType(new TagEventArgs(schema, tag)); + return false; + } + if (schema.Length > 0 && atag.Length != schema.Length) { + OnInvalidTagValue(new TagEventArgs(schema, tag)); + return false; + } + + return true; + } + + private bool VerifyList (NBT_Value tag, NBTListNode schema) + { + NBT_List ltag = tag as NBT_List; + if (ltag == null) { + OnInvalidTagType(new TagEventArgs(schema, tag)); + return false; + } + if (ltag.Count > 0 && ltag.ValueType != schema.Type) { + OnInvalidTagValue(new TagEventArgs(schema, tag)); + return false; + } + if (schema.Length > 0 && ltag.Count != schema.Length) { + OnInvalidTagValue(new TagEventArgs(schema, tag)); + return false; + } + + return true; + } + + private bool VerifyCompound (NBT_Value tag, NBTCompoundNode schema) + { + NBT_Compound ctag = tag as NBT_Compound; + if (ctag == null) { + OnInvalidTagType(new TagEventArgs(schema, tag)); + return false; + } + + bool pass = true; + + foreach (NBTSchemaNode node in schema) { + NBT_Value value; + ctag.TryGetValue(node.Name, out value); + + pass = Verify(value, node) && pass; + } + + return pass; + } + + #region Event Handlers + + protected void OnMissingTag (TagEventArgs e) + { + if (MissingTag != null) { + MissingTag(this, e); + } + } + + protected void OnInvalidTagType (TagEventArgs e) + { + if (InvalidTagType != null) { + InvalidTagType(this, e); + } + } + + protected void OnInvalidTagValue (TagEventArgs e) + { + if (InvalidTagValue != null) { + InvalidTagValue(this, e); + } + } + + #endregion + } +}