/// <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; }
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; }
/// <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(); } }
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(); } }
public static Chunk FromNbt(NbtFile nbt) { var serializer = new NbtSerializer(typeof(Chunk)); var chunk = (Chunk)serializer.Deserialize(nbt.RootTag["Level"]); return chunk; }
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; }
static Chunk() { EntityTypes = new Dictionary<string, Type>(); Serializer = new NbtSerializer(typeof(Chunk)); }
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; }
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); } }
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; }
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); } }
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."); }
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."); }
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; } }