Base class for different kinds of named binary tags.
Inheritance: ICloneable
        private void DumpTag(NbtTag tag, int level, StreamWriter writer)
        {
            for (var index = 0; index < level; index++)
                writer.Write("   ");
            writer.Write(tag.Name);
            writer.Write(" [");
            writer.Write(tag.GetType().Name);
            writer.Write("]: ");

            if (tag is NbtCompound)
            {
                writer.WriteLine("...");
                foreach (var name in ((NbtCompound)tag).Names)
                {
                    var value = tag[name];
                    this.DumpTag(value, level + 1, writer);
                }
            }
            else if (tag is NbtList)
            {
                writer.WriteLine("...");
                foreach (var item in (NbtList)tag)
                    this.DumpTag(item, level + 1, writer);
            }
            else
                writer.WriteLine(tag);
        }
Beispiel #2
0
        public static T Get <T>(NbtCompound tag, string query) where T : NbtTag
        {
            if (!query.StartsWith("/"))
            {
                throw new ArgumentException("Not query string. (Start with slash.)");
            }
            List <string> names = query.Substring(1).Split("/".ToCharArray()).ToList();

            NbtTag result = tag;

            if (names[0] == result.Name)
            {
                names.RemoveAt(0);
            }
            else
            {
                return(null);
            }

            foreach (string name in names)
            {
                result = result[name];
            }

            return((T)result);
        }
Beispiel #3
0
        private void LoadFromStreamInternal([NotNull] Stream stream, [CanBeNull] TagSelector tagSelector)
        {
            var reader = new NbtBinaryReader(stream, BigEndian)
            {
                Selector  = tagSelector,
                UseVarInt = UseVarInt
            };

            RootTag = NbtTag.ReadUnknownTag(reader);
            //else {
            //    // Make sure the first byte in this file is the tag for a TAG_Compound
            //    int firstByte = stream.ReadByte();
            //    if (firstByte < 0)
            //    {
            //        throw new EndOfStreamException();
            //    }
            //    if (firstByte != (int)NbtTagType.Compound)
            //    {
            //        throw new NbtFormatException("Given NBT stream does not start with a TAG_Compound");
            //    }

            //    var rootCompound = new NbtCompound(reader.ReadString());
            //    rootCompound.ReadTag(reader);
            //    RootTag = rootCompound;
            //}
        }
Beispiel #4
0
 public override bool IsSameContentWith(NbtTag other)
 {
     if (!(other is NbtDouble tag))
     {
         return(false);
     }
     return(tag.Value == Value);
 }
Beispiel #5
0
 public override bool IsSameContentWith(NbtTag other)
 {
     if (!(other is NbtString str))
     {
         return(false);
     }
     return(str.Value == Value);
 }
Beispiel #6
0
        public override bool IsSameContentWith(NbtTag other)
        {
            if (!(other is NbtIntArray tag))
            {
                return(false);
            }
            if (tag.Value.Length != Value.Length)
            {
                return(false);
            }

            return(Enumerable.SequenceEqual(tag.Value, Value));
        }
Beispiel #7
0
 void AddToParent([NotNull] NbtTag thisTag, [NotNull] NbtTag parent)
 {
     if (parent is NbtList parentAsList)
     {
         parentAsList.Add(thisTag);
     }
     else if (parent is NbtCompound parentAsCompound)
     {
         parentAsCompound.Add(thisTag);
     }
     else
     {
         // cannot happen unless NbtReader is bugged
         throw new NbtFormatException(InvalidParentTagError);
     }
 }
Beispiel #8
0
 /// <summary> Writes a NbtTag object, and all of its child tags, to stream.
 /// Use this method sparingly with NbtWriter -- constructing NbtTag objects defeats the purpose of this class.
 /// If you already have lots of NbtTag objects, you might as well use NbtFile to write them all at once. </summary>
 /// <param name="tag"> Tag to write. Must not be null. </param>
 /// <exception cref="NbtFormatException"> No more tags can be written -OR- given tag is unacceptable at this time. </exception>
 /// <exception cref="ArgumentNullException"> <paramref name="tag"/> is null </exception>
 public void WriteTag(NbtTag tag)
 {
     if (tag == null)
     {
         throw new ArgumentNullException("tag");
     }
     EnforceConstraints(tag.Name, tag.TagType);
     if (tag.Name != null)
     {
         tag.WriteTag(writer);
     }
     else
     {
         tag.WriteData(writer);
     }
 }
Beispiel #9
0
        internal override void ReadTag(NbtBinaryReader readStream)
        {
            ListType = readStream.ReadTagType();

            int length = readStream.ReadInt32();

            if (length < 0)
            {
                throw new NbtFormatException("Negative list size given.");
            }

            for (int i = 0; i < length; i++)
            {
                NbtTag newTag = NbtTag.Construct(ListType);
                newTag.ReadTag(readStream);
                Tags.Add(newTag);
            }
        }
Beispiel #10
0
        void AddToParent([NotNull] NbtTag thisTag, [NotNull] NbtTag parent)
        {
            var parentAsList = parent as NbtList;

            if (parentAsList != null)
            {
                parentAsList.Add(thisTag);
            }
            else
            {
                var parentAsCompound = parent as NbtCompound;
                if (parentAsCompound != null)
                {
                    parentAsCompound.Add(thisTag);
                }
                else
                {
                    // cannot happen unless NbtReader is bugged
                    throw new NbtFormatException(InvalidParentTagError);
                }
            }
        }
 public void Deserialize(NbtTag value)
 {
     NbtValue = value;
 }
Beispiel #12
0
        /// <summary> Reads the entirety of the current tag, including any descendants,
        /// and constructs an NbtTag object of the appropriate type. </summary>
        /// <returns> Constructed NbtTag object;
        /// <c>null</c> if <c>SkipEndTags</c> is <c>true</c> and trying to read an End tag. </returns>
        /// <exception cref="NbtFormatException"> If an error occured while parsing data in NBT format. </exception>
        /// <exception cref="InvalidReaderStateException"> If NbtReader cannot recover from a previous parsing error. </exception>
        /// <exception cref="EndOfStreamException"> End of stream has been reached (no more tags can be read). </exception>
        /// <exception cref="InvalidOperationException"> Tag value has already been read, and CacheTagValues is false. </exception>
        public NbtTag ReadAsTag()
        {
            switch (state)
            {
            case NbtParseState.Error:
                throw new InvalidReaderStateException(ErroneousStateError);

            case NbtParseState.AtStreamEnd:
                throw new EndOfStreamException();

            case NbtParseState.AtStreamBeginning:
            case NbtParseState.AtCompoundEnd:
                ReadToFollowing();
                break;
            }

            NbtTag parent;

            if (TagType == NbtTagType.Compound)
            {
                parent = new NbtCompound(TagName);
            }
            else if (TagType == NbtTagType.List)
            {
                parent = new NbtList(TagName, ListType);
            }
            else if (atValue)
            {
                NbtTag result = ReadValueAsTag();
                ReadToFollowing();
                return(result);
            }
            else
            {
                throw new InvalidOperationException(NoValueToReadError);
            }

            int startingDepth = Depth;
            int lastDepth     = Depth;

            do
            {
                bool end = !ReadToFollowing();
                if (end || Depth < lastDepth)
                {
                    // Going up the file tree, or end of document: wrap up
                    while (Depth <= lastDepth && parent.Parent != null)
                    {
                        parent = parent.Parent;
                        lastDepth--;
                    }
                }
                if (end || Depth <= startingDepth)
                {
                    break;
                }

                NbtTag thisTag;
                if (TagType == NbtTagType.Compound)
                {
                    thisTag = new NbtCompound(TagName);
                    AddToParent(thisTag, parent);
                    parent = thisTag;
                }
                else if (TagType == NbtTagType.List)
                {
                    thisTag = new NbtList(TagName, ListType);
                    AddToParent(thisTag, parent);
                    parent = thisTag;
                }
                else
                {
                    thisTag = ReadValueAsTag();
                    AddToParent(thisTag, parent);
                }
                lastDepth = Depth;
            } while(true);

            return(parent);
        }
Beispiel #13
0
        public void Deserialize(NbtTag value)
        {
            var compound = value as NbtCompound;
            var chunk = (Chunk)Serializer.Deserialize(value, true);

            this._TileEntities = chunk._TileEntities;
            this.Biomes = chunk.Biomes;
            this.HeightMap = chunk.HeightMap;
            this.LastUpdate = chunk.LastUpdate;
            this.Sections = chunk.Sections;
            this.TerrainPopulated = chunk.TerrainPopulated;
            this.X = chunk.X;
            this.Z = chunk.Z;

            // Entities
            var entities = compound["Entities"] as NbtList;
            Entities = new List<IDiskEntity>();
            for (int i = 0; i < entities.Count; i++)
            {
                var id = entities[i]["id"].StringValue;
                IDiskEntity entity;
                if (EntityTypes.ContainsKey(id.ToUpper()))
                    entity = (IDiskEntity)Activator.CreateInstance(EntityTypes[id]);
                else
                    entity = new UnrecognizedEntity(id);
                entity.Deserialize(entities[i]);
                Entities.Add(entity);
            }
            var serializer = new NbtSerializer(typeof(Section));
            foreach (var section in compound["Sections"] as NbtList)
            {
                int index = section["Y"].IntValue;
                Sections[index] = (Section)serializer.Deserialize(section);
                Sections[index].ProcessSection();
            }
        }
Beispiel #14
0
 /// <summary> Creates an empty NbtFile.
 /// RootTag will be set to an empty <c>NbtCompound</c> with a blank name (""). </summary>
 public NbtFile()
 {
     BigEndian  = BigEndianByDefault;
     BufferSize = DefaultBufferSize;
     rootTag    = new NbtCompound("");
 }
Beispiel #15
0
        public object Deserialize(NbtTag value, bool skipInterfaceCheck = false)
        {
            if (!skipInterfaceCheck && typeof(INbtSerializable).IsAssignableFrom(Type))
            {
                var instance = (INbtSerializable)Activator.CreateInstance(Type);
                instance.Deserialize(value);
                return instance;
            }
            if (value is NbtByte)
                return ((NbtByte)value).Value;
            else if (value is NbtByteArray)
                return ((NbtByteArray)value).Value;
            else if (value is NbtDouble)
                return ((NbtDouble)value).Value;
            else if (value is NbtFloat)
                return ((NbtFloat)value).Value;
            else if (value is NbtInt)
                return ((NbtInt)value).Value;
            else if (value is NbtIntArray)
                return ((NbtIntArray)value).Value;
            else if (value is NbtLong)
                return ((NbtLong)value).Value;
            else if (value is NbtShort)
                return ((NbtShort)value).Value;
            else if (value is NbtString)
                return ((NbtString)value).Value;
            else if (value is NbtList)
            {
                var list = (NbtList)value;
                var type = typeof(object);
                if (list.ListType == NbtTagType.Byte)
                    type = typeof(byte);
                else if (list.ListType == NbtTagType.ByteArray)
                    type = typeof(byte[]);
                else if (list.ListType == NbtTagType.Compound)
                {
                    if (Type.IsArray)
                        type = Type.GetElementType();
                    else
                        type = typeof(object);
                }
                else if (list.ListType == NbtTagType.Double)
                    type = typeof(double);
                else if (list.ListType == NbtTagType.Float)
                    type = typeof(float);
                else if (list.ListType == NbtTagType.Int)
                    type = typeof(int);
                else if (list.ListType == NbtTagType.IntArray)
                    type = typeof(int[]);
                else if (list.ListType == NbtTagType.Long)
                    type = typeof(long);
                else if (list.ListType == NbtTagType.Short)
                    type = typeof(short);
                else if (list.ListType == NbtTagType.String)
                    type = typeof(string);
                else
                    throw new NotSupportedException("The NBT list type '" + list.TagType + "' is not supported.");
                var array = Array.CreateInstance(type, list.Count);
                var innerSerializer = new NbtSerializer(type);
                for (int i = 0; i < array.Length; i++)
                    array.SetValue(innerSerializer.Deserialize(list[i]), i);
                return array;
            }
            else if(value is NbtCompound)
            {
                var compound = value as NbtCompound;
                var properties = Type.GetProperties().Where(p =>
                    !Attribute.GetCustomAttributes(p, typeof(NbtIgnoreAttribute)).Any());
                var resultObject = Activator.CreateInstance(Type);
                foreach (var property in properties)
                {
                    if (!property.CanWrite)
                        continue;
                    string name = property.Name;
                    var nameAttributes = Attribute.GetCustomAttributes(property, typeof(TagNameAttribute));

                    if (nameAttributes.Length != 0)
                        name = ((TagNameAttribute)nameAttributes[0]).Name;
                    var node = compound.Tags.SingleOrDefault(a => a.Name == name);
                    if (node == null) continue;
                    object data;
                    if (typeof(INbtSerializable).IsAssignableFrom(property.PropertyType))
                    {
                        data = Activator.CreateInstance(property.PropertyType);
                        ((INbtSerializable)data).Deserialize(node);
                    }
                    else
                        data = new NbtSerializer(property.PropertyType).Deserialize(node);

                    // Some manual casting for edge cases
                    if (property.PropertyType == typeof(bool)
                        && data is byte)
                        data = (byte)data == 1;
                    if (property.PropertyType == typeof(sbyte) && data is byte)
                        data = (sbyte)(byte)data;

                    property.SetValue(resultObject, data, null);
                }

                return resultObject;
            }

            throw new NotSupportedException("The node type '" + value.GetType() + "' is not supported.");
        }
Beispiel #16
0
 public abstract bool IsSameContentWith(NbtTag other);
Beispiel #17
0
 public void Deserialize(NbtTag value)
 {
     Data = value.ByteArrayValue;
 }
Beispiel #18
0
        public void Deserialize(NbtTag value)
        {
            var tag = (NbtCompound)value;

            X = tag["X"].IntValue;
            Z = tag["Z"].IntValue;
            if (tag.Contains("TerrainPopulated"))
                TerrainPopulated = tag["TerrainPopulated"].ByteValue > 0;
            if (tag.Contains("LightPopulated"))
                LightPopulated = tag["LightPopulated"].ByteValue > 0;
            Blocks = tag["Blocks"].ByteArrayValue;
            Metadata = new NibbleArray();
            Metadata.Data = tag["Data"].ByteArrayValue;
            BlockLight = new NibbleArray();
            BlockLight.Data = tag["BlockLight"].ByteArrayValue;
            SkyLight = new NibbleArray();
            SkyLight.Data = tag["SkyLight"].ByteArrayValue;
            
            if (tag.Contains("TileEntities"))
            {
                foreach (var entity in tag["TileEntities"] as NbtList)
                {
                    TileEntities[new Coordinates3D(entity["coordinates"][0].IntValue,
                        entity["coordinates"][1].IntValue,
                        entity["coordinates"][2].IntValue)] = entity["value"][0] as NbtCompound;
                }
            }
            UpdateHeightMap();

            // TODO: Entities
        }
Beispiel #19
0
        public NbtTag ReadAsTag()
        {
            switch (state)
            {
            case NbtParseState.Error:
                throw new InvalidReaderStateException(ErroneousStateError);

            case NbtParseState.AtStreamEnd:
                throw new EndOfStreamException();

            case NbtParseState.AtStreamBeginning:
            case NbtParseState.AtCompoundEnd:
                ReadToFollowing();
                break;
            }

            // get this tag
            NbtTag parent;

            if (TagType == NbtTagType.Compound)
            {
                parent = new NbtCompound(TagName);
            }
            else if (TagType == NbtTagType.List)
            {
                parent = new NbtList(TagName, ListType);
            }
            else if (atValue)
            {
                NbtTag result = ReadValueAsTag();
                ReadToFollowing();
                // if we're at a value tag, there are no child tags to read
                return(result);
            }
            else
            {
                // end tags cannot be read-as-tags (there is no corresponding NbtTag object)
                throw new InvalidOperationException(NoValueToReadError);
            }

            int startingDepth = Depth;
            int parentDepth   = Depth;

            do
            {
                ReadToFollowing();
                // Going up the file tree, or end of document: wrap up
                while (Depth <= parentDepth && parent.Parent != null)
                {
                    parent = parent.Parent;
                    parentDepth--;
                }
                if (Depth <= startingDepth)
                {
                    break;
                }

                NbtTag thisTag;
                if (TagType == NbtTagType.Compound)
                {
                    thisTag = new NbtCompound(TagName);
                    AddToParent(thisTag, parent);
                    parent      = thisTag;
                    parentDepth = Depth;
                }
                else if (TagType == NbtTagType.List)
                {
                    thisTag = new NbtList(TagName, ListType);
                    AddToParent(thisTag, parent);
                    parent      = thisTag;
                    parentDepth = Depth;
                }
                else if (TagType != NbtTagType.End)
                {
                    thisTag = ReadValueAsTag();
                    AddToParent(thisTag, parent);
                }
            } while (true);

            return(parent);
        }
Beispiel #20
0
        public void Deserialize(NbtTag value)
        {
            var chunk = new Chunk();
            var tag = (NbtCompound)value;

            Biomes = chunk.Biomes;
            HeightMap = chunk.HeightMap;
            LastUpdate = chunk.LastUpdate;
            TerrainPopulated = chunk.TerrainPopulated;
            X = tag["X"].IntValue;
            Z = tag["Z"].IntValue;
            Blocks = tag["Blocks"].ByteArrayValue;
            Metadata = new NibbleArray();
            Metadata.Data = tag["Data"].ByteArrayValue;
            BlockLight = new NibbleArray();
            BlockLight.Data = tag["BlockLight"].ByteArrayValue;
            SkyLight = new NibbleArray();
            SkyLight.Data = tag["SkyLight"].ByteArrayValue;

            if (tag.Contains("TileEntities"))
            {
                foreach (var entity in tag["TileEntities"] as NbtList)
                {
                    TileEntities[new Coordinates3D(entity["coordinates"][0].IntValue,
                        entity["coordinates"][1].IntValue,
                        entity["coordinates"][2].IntValue)] = entity["value"][0] as NbtCompound;
                }
            }

            // TODO: Entities
        }
Beispiel #21
0
        public object Deserialize(NbtTag value)
        {
            if (value is NbtByte)
                return ((NbtByte)value).Value;
            else if (value is NbtByteArray)
                return ((NbtByteArray)value).Value;
            else if (value is NbtDouble)
                return ((NbtDouble)value).Value;
            else if (value is NbtFloat)
                return ((NbtFloat)value).Value;
            else if (value is NbtInt)
                return ((NbtInt)value).Value;
            else if (value is NbtIntArray)
                return ((NbtIntArray)value).Value;
            else if (value is NbtLong)
                return ((NbtLong)value).Value;
            else if (value is NbtShort)
                return ((NbtShort)value).Value;
            else if (value is NbtString)
                return ((NbtString)value).Value;
            else if(value is NbtCompound)
            {
                var compound = value as NbtCompound;
                var properties = Type.GetProperties().Where(p =>
                    !Attribute.GetCustomAttributes(p, typeof(NbtIgnoreAttribute)).Any());
                var resultObject = Activator.CreateInstance(Type);
                foreach (var property in properties)
                {
                    if (!property.CanWrite)
                        continue;
                    string name = property.Name;
                    var nameAttributes = Attribute.GetCustomAttributes(property, typeof(TagNameAttribute));

                    if (nameAttributes.Length != 0)
                        name = ((TagNameAttribute)nameAttributes[0]).Name;
                    var node = compound.Tags.SingleOrDefault(a => a.Name == name);
                    if (node == null) continue;
                    var data = new NbtSerializer(property.PropertyType).Deserialize(node);

                    if (property.PropertyType == typeof(bool)
                        && data is byte)
                        data = (byte)data == 1;

                    property.SetValue(resultObject, data, null);
                }
                
                return resultObject;
            }
            
            throw new NotSupportedException("The node type '" + value.GetType() + "' is not supported.");
        }
Beispiel #22
0
 static bool HeaderTagSelector( NbtTag tag ) {
     return tag.Parent == null || tag.Parent.Name != "MapData" || tag.Name != "BlockData";
 }