Example #1
0
 /// <summary>
 /// Loads a level from the given level.dat file.
 /// </summary>
 public static Level Load(string file)
 {
     if (!Path.IsPathRooted(file))
         file = Path.Combine(Directory.GetCurrentDirectory(), file);
     var serializer = new NbtSerializer(typeof(Level));
     var nbtFile = new NbtFile(file);
     var level = (Level)serializer.Deserialize(nbtFile.RootTag["Data"]);
     level.DatFile = file;
     level.BaseDirectory = Path.GetDirectoryName(file);
     level.WorldGenerator = GetGenerator(level.GeneratorName);
     level.WorldGenerator.Initialize(level);
     var worlds = Directory.GetDirectories(level.BaseDirectory).Where(
         d => Directory.GetFiles(d).Any(f => f.EndsWith(".mca") || f.EndsWith(".mcr")));
     foreach (var world in worlds)
     {
         var w = World.LoadWorld(world);
         w.WorldGenerator = level.WorldGenerator;
         level.AddWorld(w);
     }
     return level;
 }
Example #2
0
 public NbtFile ToNbt()
 {
     var serializer = new NbtSerializer(typeof(Chunk));
     var compound = serializer.Serialize(this, "Level") as NbtCompound;
     var file = new NbtFile();
     file.RootTag.Add(compound);
     return file;
 }
Example #3
0
 /// <summary>
 /// Saves this level. This will not work with an in-memory world.
 /// </summary>
 public void Save()
 {
     if (DatFile == null)
         throw new InvalidOperationException("This level exists only in memory. Use Save(string).");
     LastPlayed = DateTime.UtcNow.Ticks;
     var serializer = new NbtSerializer(typeof(Level));
     var tag = serializer.Serialize(this, "Data") as NbtCompound;
     var file = new NbtFile();
     file.RootTag.Add(tag);
     file.SaveToFile(DatFile, NbtCompression.GZip);
     // Save worlds
     foreach (var world in Worlds)
     {
         if (world.BaseDirectory == null)
             world.Save(Path.Combine(BaseDirectory, world.Name));
         else
             world.Save();
     }
 }
Example #4
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();
            }
        }
Example #5
0
 public static Chunk FromNbt(NbtFile nbt)
 {
     var serializer = new NbtSerializer(typeof(Chunk));
     var chunk = (Chunk)serializer.Deserialize(nbt.RootTag["Level"]);
     return chunk;
 }
Example #6
0
 public NbtTag Serialize(string tagName)
 {
     var chunk = (NbtCompound)Serializer.Serialize(this, tagName, true);
     var entities = new NbtList("Entities", NbtTagType.Compound);
     for (int i = 0; i < Entities.Count; i++)
         entities.Add(Entities[i].Serialize(string.Empty));
     chunk.Add(entities);
     var sections = new NbtList("Sections", NbtTagType.Compound);
     var serializer = new NbtSerializer(typeof(Section));
     for (int i = 0; i < Sections.Length; i++)
     {
         if (!Sections[i].IsAir)
             sections.Add(serializer.Serialize(Sections[i]));
     }
     chunk.Add(sections);
     return chunk;
 }
Example #7
0
 static Chunk()
 {
     EntityTypes = new Dictionary<string, Type>();
     Serializer = new NbtSerializer(typeof(Chunk));
 }
Example #8
0
        NbtTag SerializeList(string tagName, IList valueAsArray, Type elementType, NullPolicy elementNullPolicy)
        {
            NbtTagType listType;
            if (elementType == typeof(byte) || elementType == typeof(sbyte) || elementType == typeof(bool)) {
                listType = NbtTagType.Byte;
            } else if (elementType == typeof(byte[])) {
                listType = NbtTagType.ByteArray;
            } else if (elementType == typeof(double)) {
                listType = NbtTagType.Double;
            } else if (elementType == typeof(float)) {
                listType = NbtTagType.Float;
            } else if (elementType == typeof(int) || elementType == typeof(uint)) {
                listType = NbtTagType.Int;
            } else if (elementType == typeof(int[])) {
                listType = NbtTagType.IntArray;
            } else if (elementType == typeof(long) || elementType == typeof(ulong)) {
                listType = NbtTagType.Long;
            } else if (elementType == typeof(short) || elementType == typeof(ushort)) {
                listType = NbtTagType.Short;
            } else if (elementType == typeof(string)) {
                listType = NbtTagType.String;
            } else {
                listType = NbtTagType.Compound;
            }

            var list = new NbtList(tagName, listType);

            if (elementType.IsPrimitive) {
                // speedy serialization for basic types
                for (int i = 0; i < valueAsArray.Count; i++) {
                    list.Add(SerializePrimitiveType(null, valueAsArray[i]));
                }
            } else if (SerializationUtil.IsDirectlyMappedType(elementType)) {
                // speedy serialization for directly-mapped types
                for (int i = 0; i < valueAsArray.Count; i++) {
                    var value = valueAsArray[i];
                    if (value == null) {
                        switch (elementNullPolicy) {
                            case NullPolicy.Error:
                                throw new NullReferenceException("Null elements not allowed for tag " + tagName);
                            case NullPolicy.InsertDefault:
                                list.Add(Serialize(SerializationUtil.GetDefaultValue(elementType), true));
                                break;
                            case NullPolicy.Ignore:
                                continue;
                        }
                    } else {
                        list.Add(Serialize(valueAsArray[i], true));
                    }
                }
            } else {
                // serialize complex types
                var innerSerializer = new NbtSerializer(elementType);
                for (int i = 0; i < valueAsArray.Count; i++) {
                    var value = valueAsArray[i];
                    if (value == null) {
                        switch (elementNullPolicy) {
                            case NullPolicy.Error:
                                throw new NullReferenceException("Null elements not allowed for tag " + tagName);
                            case NullPolicy.Ignore:
                                continue;
                            case NullPolicy.InsertDefault:
                                // TODO
                                break;
                        }
                    } else {
                        list.Add(innerSerializer.Serialize(valueAsArray[i], null));
                    }
                }
            }
            return list;
        }
Example #9
0
        public object Deserialize(NbtTag tag, bool skipInterfaceCheck = false)
        {
            if (!skipInterfaceCheck && typeof(INbtSerializable).IsAssignableFrom(Type)) {
                var instance = (INbtSerializable)Activator.CreateInstance(Type);
                instance.Deserialize(tag);
                return instance;
            }
            switch (tag.TagType) {
                case NbtTagType.List:
                    var list = (NbtList)tag;
                    Type type;
                    switch (list.ListType) {
                        case NbtTagType.Byte:
                            type = typeof(byte);
                            break;
                        case NbtTagType.ByteArray:
                            type = typeof(byte[]);
                            break;
                        case NbtTagType.List:
                            type = Type.GetElementType() ?? typeof(object);
                            break;
                        case NbtTagType.Double:
                            type = typeof(double);
                            break;
                        case NbtTagType.Float:
                            type = typeof(float);
                            break;
                        case NbtTagType.Int:
                            type = typeof(int);
                            break;
                        case NbtTagType.IntArray:
                            type = typeof(int[]);
                            break;
                        case NbtTagType.Long:
                            type = typeof(long);
                            break;
                        case NbtTagType.Short:
                            type = typeof(short);
                            break;
                        case NbtTagType.String:
                            type = typeof(string);
                            break;
                        default:
                            throw new NotSupportedException("The NBT list type '" + list.TagType +
                                                            "' is not supported.");
                    }
                    Array array = Array.CreateInstance(type, list.Count);
                    if (type.IsPrimitive || type.IsArray || type == typeof(string)) {
                        for (int i = 0; i < array.Length; i++) {
                            array.SetValue(DeserializeSimpleType(list[i]), i);
                        }
                    } else {
                        var innerSerializer = new NbtSerializer(type);
                        for (int i = 0; i < array.Length; i++) {
                            array.SetValue(innerSerializer.Deserialize(list[i]), i);
                        }
                    }
                    return array;

                case NbtTagType.Compound:
                    if (!propertyInfoRead) ReadPropertyInfo();
                    var compound = (NbtCompound)tag;

                    object resultObject = Activator.CreateInstance(Type);
                    foreach (PropertyInfo property in properties) {
                        if (!property.CanWrite) continue;
                        string name = propertyTagNames[property];

                        NbtTag node;
                        if (!compound.TryGet(name, out node)) 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;
                        }

                        if (property.PropertyType.IsInstanceOfType(data)) {
                            property.SetValue(resultObject, data, null);
                        } else {
                            property.SetValue(resultObject, Convert.ChangeType(data, property.PropertyType), null);
                        }
                    }

                    return resultObject;

                default:
                    return DeserializeSimpleType(tag);
            }
        }
Example #10
0
        public NbtTag Serialize(object value, string tagName, bool skipInterfaceCheck = false,
                                NullPolicy thisNullPolicy = NullPolicy.Error,
                                NullPolicy elementNullPolicy = NullPolicy.Error)
        {
            if (value == null) {
                return new NbtCompound(tagName);
            }

            Type realType = value.GetType();
            if (realType.IsPrimitive) {
                return SerializePrimitiveType(tagName, value);
            }

            var valueAsString = value as string;
            if (valueAsString != null) {
                return new NbtString(tagName, valueAsString);
            }

            // Serialize arrays
            var valueAsArray = value as Array;
            if (valueAsArray != null) {
                var valueAsByteArray = value as byte[];
                if (valueAsByteArray != null) {
                    return new NbtByteArray(tagName, valueAsByteArray);
                }

                var valueAsIntArray = value as int[];
                if (valueAsIntArray != null) {
                    return new NbtIntArray(tagName, valueAsIntArray);
                }

                Type elementType = realType.GetElementType();
                return SerializeList(tagName, valueAsArray, elementType, elementNullPolicy);
            }

            if (!skipInterfaceCheck && value is INbtSerializable) {
                return ((INbtSerializable)value).Serialize(tagName);
            }

            // Serialize ILists
            if (realType.IsGenericType && realType.GetGenericTypeDefinition() == typeof(List<>)) {
                Type listType = realType.GetGenericArguments()[0];
                return SerializeList(tagName, (IList)value, listType, elementNullPolicy);
            }

            // Skip serializing NbtTags and NbtFiles
            var valueAsTag = value as NbtTag;
            if (valueAsTag != null) {
                return valueAsTag;
            }
            var file = value as NbtFile;
            if (file != null) {
                return file.RootTag;
            }

            // Fallback for compound tags
            var compound = new NbtCompound(tagName);
            if (!propertyInfoRead) ReadPropertyInfo();

            foreach (PropertyInfo property in properties) {
                if (!property.CanRead) continue;
                Type propType = property.PropertyType;
                object propValue = property.GetValue(value, null);

                // Handle null property values
                if (propValue == null) {
                    NullPolicy selfNullPolicy = GetElementPolicy(property);
                    switch (selfNullPolicy) {
                        case NullPolicy.Ignore:
                            continue;
                        case NullPolicy.Error:
                            throw new NullReferenceException("Null values not allowed for property " + property.Name);
                        case NullPolicy.InsertDefault:
                            propValue = SerializationUtil.GetDefaultValue(propType);
                            break;
                    }
                }

                string propTagName = propertyTagNames[property];
                NbtTag tag;
                if (propType.IsPrimitive) {
                    tag = SerializePrimitiveType(propTagName, propValue);
                } else if (propType.IsArray || propType == typeof(string)) {
                    tag = Serialize(propValue, propTagName);
                } else {
                    var innerSerializer = new NbtSerializer(property.PropertyType);
                    tag = innerSerializer.Serialize(propValue, propTagName);
                }
                compound.Add(tag);
            }

            return compound;
        }
Example #11
0
        public NbtTag Serialize(object value, string tagName, bool skipInterfaceCheck = false)
        {
            if (!skipInterfaceCheck && value is INbtSerializable)
            {
                return(((INbtSerializable)value).Serialize(tagName));
            }
            else if (value is NbtTag)
            {
                return((NbtTag)value);
            }
            else if (value is byte)
            {
                return(new NbtByte(tagName, (byte)value));
            }
            else if (value is sbyte)
            {
                return(new NbtByte(tagName, (byte)(sbyte)value));
            }
            else if (value is bool)
            {
                return(new NbtByte(tagName, (byte)((bool)value ? 1 : 0)));
            }
            else if (value is byte[])
            {
                return(new NbtByteArray(tagName, (byte[])value));
            }
            else if (value is double)
            {
                return(new NbtDouble(tagName, (double)value));
            }
            else if (value is float)
            {
                return(new NbtFloat(tagName, (float)value));
            }
            else if (value is int)
            {
                return(new NbtInt(tagName, (int)value));
            }
            else if (value is uint)
            {
                return(new NbtInt(tagName, (int)(uint)value));
            }
            else if (value is int[])
            {
                return(new NbtIntArray(tagName, (int[])value));
            }
            else if (value is long)
            {
                return(new NbtLong(tagName, (long)value));
            }
            else if (value is ulong)
            {
                return(new NbtLong(tagName, (long)(ulong)value));
            }
            else if (value is short)
            {
                return(new NbtShort(tagName, (short)value));
            }
            else if (value is ushort)
            {
                return(new NbtShort(tagName, (short)(ushort)value));
            }
            else if (value is string)
            {
                return(new NbtString(tagName, (string)value));
            }
            else if (value.GetType().IsArray)
            {
                var elementType = value.GetType().GetElementType();
                var array       = value as Array;
                var listType    = NbtTagType.Compound;
                if (elementType == typeof(byte) || elementType == typeof(sbyte))
                {
                    listType = NbtTagType.Byte;
                }
                else if (elementType == typeof(bool))
                {
                    listType = NbtTagType.Byte;
                }
                else if (elementType == typeof(byte[]))
                {
                    listType = NbtTagType.ByteArray;
                }
                else if (elementType == typeof(double))
                {
                    listType = NbtTagType.Double;
                }
                else if (elementType == typeof(float))
                {
                    listType = NbtTagType.Float;
                }
                else if (elementType == typeof(int) || elementType == typeof(uint))
                {
                    listType = NbtTagType.Int;
                }
                else if (elementType == typeof(int[]))
                {
                    listType = NbtTagType.IntArray;
                }
                else if (elementType == typeof(long) || elementType == typeof(ulong))
                {
                    listType = NbtTagType.Long;
                }
                else if (elementType == typeof(short) || elementType == typeof(ushort))
                {
                    listType = NbtTagType.Short;
                }
                else if (elementType == typeof(string))
                {
                    listType = NbtTagType.String;
                }
                var list            = new NbtList(tagName, listType);
                var innerSerializer = new NbtSerializer(elementType);
                for (int i = 0; i < array.Length; i++)
                {
                    list.Add(innerSerializer.Serialize(array.GetValue(i)));
                }
                return(list);
            }
            else if (value is NbtFile)
            {
                return(((NbtFile)value).RootTag);
            }
            else
            {
                var compound = new NbtCompound(tagName);

                if (value == null)
                {
                    return(compound);
                }
                var nameAttributes = Attribute.GetCustomAttributes(value.GetType(), typeof(TagNameAttribute));

                if (nameAttributes.Length > 0)
                {
                    compound = new NbtCompound(((TagNameAttribute)nameAttributes[0]).Name);
                }

                var properties = Type.GetProperties().Where(p => !Attribute.GetCustomAttributes(p,
                                                                                                typeof(NbtIgnoreAttribute)).Any());

                foreach (var property in properties)
                {
                    if (!property.CanRead)
                    {
                        continue;
                    }

                    NbtTag tag = null;

                    string name = property.Name;
                    nameAttributes = Attribute.GetCustomAttributes(property, typeof(TagNameAttribute));
                    var ignoreOnNullAttribute = Attribute.GetCustomAttribute(property, typeof(IgnoreOnNullAttribute));
                    if (nameAttributes.Length != 0)
                    {
                        name = ((TagNameAttribute)nameAttributes[0]).Name;
                    }

                    var innerSerializer = new NbtSerializer(property.PropertyType);
                    var propValue       = property.GetValue(value, null);

                    if (propValue == null)
                    {
                        if (ignoreOnNullAttribute != null)
                        {
                            continue;
                        }
                        if (property.PropertyType.IsValueType)
                        {
                            propValue = Activator.CreateInstance(property.PropertyType);
                        }
                        else if (property.PropertyType == typeof(string))
                        {
                            propValue = "";
                        }
                    }

                    tag = innerSerializer.Serialize(propValue, name);
                    compound.Add(tag);
                }

                return(compound);
            }
        }
Example #12
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.");
        }
Example #13
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.");
        }
Example #14
0
        public NbtTag Serialize(object value, string tagName, bool skipInterfaceCheck = false)
        {
            if (!skipInterfaceCheck && value is INbtSerializable)
                return ((INbtSerializable)value).Serialize(tagName);
            else if (value is NbtTag)
                return (NbtTag)value;
            else if (value is byte)
                return new NbtByte(tagName, (byte)value);
            else if (value is sbyte)
                return new NbtByte(tagName, (byte)(sbyte)value);
            else if (value is bool)
                return new NbtByte(tagName, (byte)((bool)value ? 1 : 0));
            else if (value is byte[])
                return new NbtByteArray(tagName, (byte[])value);
            else if (value is double)
                return new NbtDouble(tagName, (double)value);
            else if (value is float)
                return new NbtFloat(tagName, (float)value);
            else if (value is int)
                return new NbtInt(tagName, (int)value);
            else if (value is uint)
                return new NbtInt(tagName, (int)(uint)value);
            else if (value is int[])
                return new NbtIntArray(tagName, (int[])value);
            else if (value is long)
                return new NbtLong(tagName, (long)value);
            else if (value is ulong)
                return new NbtLong(tagName, (long)(ulong)value);
            else if (value is short)
                return new NbtShort(tagName, (short)value);
            else if (value is ushort)
                return new NbtShort(tagName, (short)(ushort)value);
            else if (value is string)
                return new NbtString(tagName, (string)value);
            else if (value.GetType().IsArray)
            {
                var elementType = value.GetType().GetElementType();
                var array = value as Array;
                var listType = NbtTagType.Compound;
                if (elementType == typeof (byte) || elementType == typeof (sbyte))
                    listType = NbtTagType.Byte;
                else if (elementType == typeof (bool))
                    listType = NbtTagType.Byte;
                else if (elementType == typeof (byte[]))
                    listType = NbtTagType.ByteArray;
                else if (elementType == typeof (double))
                    listType = NbtTagType.Double;
                else if (elementType == typeof (float))
                    listType = NbtTagType.Float;
                else if (elementType == typeof (int) || elementType == typeof (uint))
                    listType = NbtTagType.Int;
                else if (elementType == typeof (int[]))
                    listType = NbtTagType.IntArray;
                else if (elementType == typeof (long) || elementType == typeof (ulong))
                    listType = NbtTagType.Long;
                else if (elementType == typeof (short) || elementType == typeof (ushort))
                    listType = NbtTagType.Short;
                else if (elementType == typeof (string))
                    listType = NbtTagType.String;
                var list = new NbtList(tagName, listType);
                var innerSerializer = new NbtSerializer(elementType);
                for (int i = 0; i < array.Length; i++)
                    list.Add(innerSerializer.Serialize(array.GetValue(i)));
                return list;
            }
            else if (value is NbtFile)
                return ((NbtFile)value).RootTag;
            else
            {
                var compound = new NbtCompound(tagName);

                if (value == null) return compound;
                var nameAttributes = Attribute.GetCustomAttributes(value.GetType(), typeof (TagNameAttribute));

                if (nameAttributes.Length > 0)
                    compound = new NbtCompound(((TagNameAttribute)nameAttributes[0]).Name);

                var properties = Type.GetProperties().Where(p => !Attribute.GetCustomAttributes(p,
                    typeof (NbtIgnoreAttribute)).Any());

                foreach (var property in properties)
                {
                    if (!property.CanRead)
                        continue;

                    NbtTag tag = null;

                    string name = property.Name;
                    nameAttributes = Attribute.GetCustomAttributes(property, typeof (TagNameAttribute));
                    var ignoreOnNullAttribute = Attribute.GetCustomAttribute(property, typeof(IgnoreOnNullAttribute));
                    if (nameAttributes.Length != 0)
                        name = ((TagNameAttribute)nameAttributes[0]).Name;

                    var innerSerializer = new NbtSerializer(property.PropertyType);
                    var propValue = property.GetValue(value, null);

                    if (propValue == null)
                    {
                        if (ignoreOnNullAttribute != null) continue;
                        if (property.PropertyType.IsValueType)
                        {
                            propValue = Activator.CreateInstance(property.PropertyType);
                        }
                        else if (property.PropertyType == typeof (string))
                            propValue = "";
                    }

                    tag = innerSerializer.Serialize(propValue, name);
                    compound.Add(tag);
                }

                return compound;
            }
        }