示例#1
0
        public static NMSTemplate DeserializeEXml(EXmlData xmlData)
        {
            NMSTemplate template       = TemplateFromName(xmlData.Template);
            Type        templateType   = template.GetType();
            var         templateFields = templateType.GetFields().OrderBy(field => field.MetadataToken); // hack to get fields in order of declaration (todo: use something less hacky, this might break mono?)

            foreach (var templateField in templateFields)
            {
                NMSAttribute settings = templateField.GetCustomAttribute <NMSAttribute>();
                if (settings?.DefaultValue != null)
                {
                    templateField.SetValue(template, settings.DefaultValue);
                }
            }

            foreach (var xmlProperty in xmlData.Elements.OfType <EXmlProperty>())
            {
                FieldInfo    field      = templateType.GetField(xmlProperty.Name);
                Type         fieldType  = field.FieldType;
                NMSAttribute settings   = field.GetCustomAttribute <NMSAttribute>();
                object       fieldValue = DeserializeEXmlValue(template, fieldType, field, xmlProperty, templateType, settings);
                field.SetValue(template, fieldValue);
            }

            foreach (EXmlData innerXmlData in xmlData.Elements.OfType <EXmlData>())
            {
                FieldInfo   field         = templateType.GetField(innerXmlData.Name);
                NMSTemplate innerTemplate = DeserializeEXml(innerXmlData);
                field.SetValue(template, innerTemplate);
            }

            return(template);
        }
示例#2
0
        public static NMSTemplate DeserializeBinaryTemplate(BinaryReader reader, string templateName)
        {
            if (templateName.StartsWith("c") && templateName.Length > 1)
            {
                templateName = templateName.Substring(1);
            }

            NMSTemplate obj = TemplateFromName(templateName);

            if (obj == null)
            {
                return(null);
            }

            long templatePosition = reader.BaseStream.Position;

            if (PrintToDebug)
            {
                Debug.WriteLine($"{templateName} position: 0x{templatePosition:X}");
            }

            if (templateName == "VariableSizeString")
            {
                long stringPos    = reader.ReadInt64();
                int  stringLength = reader.ReadInt32();
                int  unkC         = reader.ReadInt32();
                reader.BaseStream.Position      = templatePosition + stringPos;
                ((VariableSizeString)obj).Value = reader.ReadString(Encoding.UTF8, stringLength);
                reader.BaseStream.Position      = templatePosition + 0x10;
                return(obj);
            }

            var type   = obj.GetType();
            var fields = type.GetFields().OrderBy(field => field.MetadataToken); // hack to get fields in order of declaration (todo: use something less hacky, this might break mono?)

            foreach (var field in fields)
            {
                NMSAttribute settings = field.GetCustomAttribute <NMSAttribute>();
                field.SetValue(obj, DeserializeValue(reader, field.FieldType, settings, templatePosition, field, obj));
            }

            obj.FinishDeserialize();

            if (PrintToDebug)
            {
                Debug.WriteLine($"{templateName} end position: 0x{reader.BaseStream.Position:X}");
            }

            return(obj);
        }
示例#3
0
        public static NMSTemplate DeserializeEXml(EXmlData xmlData)
        {
            NMSTemplate template     = TemplateFromName(xmlData.Template);
            Type        templateType = template.GetType();

            foreach (var xmlProperty in xmlData.Elements.OfType <EXmlProperty>())
            {
                FieldInfo field     = templateType.GetField(xmlProperty.Name);
                Type      fieldType = field.FieldType;
                object    fieldValue;
                switch (fieldType.Name)
                {
                case "String":
                    fieldValue = xmlProperty.Value;
                    break;

                case "Single":
                    fieldValue = float.Parse(xmlProperty.Value);
                    break;

                case "Boolean":
                    fieldValue = bool.Parse(xmlProperty.Value);
                    break;

                case "Int16":
                    fieldValue = short.Parse(xmlProperty.Value);
                    break;

                case "Int32":
                    var valuesMethod = templateType.GetMethod(field.Name + "Values");
                    if (valuesMethod != null)
                    {
                        if (String.IsNullOrEmpty(xmlProperty.Value))
                        {
                            fieldValue = (int)-1;
                        }
                        else
                        {
                            string[] values = (string[])valuesMethod.Invoke(template, null);
                            fieldValue = Array.FindIndex(values, v => v == xmlProperty.Value);
                        }
                    }
                    else
                    {
                        fieldValue = int.Parse(xmlProperty.Value);
                    }
                    break;

                case "Int64":
                    fieldValue = long.Parse(xmlProperty.Value);
                    break;

                case "Byte[]":
                    fieldValue = xmlProperty.Value == null ? null : Convert.FromBase64String(xmlProperty.Value);
                    break;

                case "List`1":
                    Type  elementType = fieldType.GetGenericArguments()[0];
                    Type  listType    = typeof(List <>).MakeGenericType(elementType);
                    IList list        = (IList)Activator.CreateInstance(listType);
                    foreach (EXmlData innerXmlData in xmlProperty.Elements.OfType <EXmlData>())
                    {
                        NMSTemplate element = DeserializeEXml(innerXmlData);
                        list.Add(element);
                    }

                    fieldValue = list;
                    break;

                default:
                    fieldValue = fieldType.IsValueType ? Activator.CreateInstance(fieldType) : null;
                    break;
                }

                field.SetValue(template, fieldValue);
            }

            foreach (EXmlData innerXmlData in xmlData.Elements.OfType <EXmlData>())
            {
                FieldInfo   field         = templateType.GetField(innerXmlData.Name);
                NMSTemplate innerTemplate = DeserializeEXml(innerXmlData);
                field.SetValue(template, innerTemplate);
            }

            return(template);
        }
示例#4
0
        public static NMSTemplate DeserializeBinaryTemplate(BinaryReader reader, string templateName)
        {
            if (templateName.StartsWith("c") && templateName.Length > 1)
            {
                templateName = templateName.Substring(1);
            }

            NMSTemplate obj = TemplateFromName(templateName);

            if (obj == null)
            {
                return(null);
            }

            long templatePosition = reader.BaseStream.Position;

            System.Diagnostics.Debug.Print(templateName + " position: " + templatePosition.ToString("X"));

            if (templateName == "VariableSizeString")
            {
                long stringPos    = reader.ReadInt64();
                int  stringLength = reader.ReadInt32();
                int  unkC         = reader.ReadInt32();
                reader.BaseStream.Position      = templatePosition + stringPos;
                ((VariableSizeString)obj).Value = reader.ReadString(Encoding.UTF8, stringLength);
                reader.BaseStream.Position      = templatePosition + 0x10;
                return(obj);
            }

            var type   = obj.GetType();
            var fields = type.GetFields().OrderBy(field => field.MetadataToken); // hack to get fields in order of declaration (todo: use something less hacky, this might break mono?)

            foreach (var field in fields)
            {
                var fieldAddr = reader.BaseStream.Position - templatePosition;
                var fieldName = field.Name;
                var fieldType = field.FieldType.Name;
                switch (fieldType)
                {
                case "String":
                case "Byte[]":
                    int size = 0;
                    foreach (var attr in field.CustomAttributes)
                    {
                        if (attr.AttributeType.Name != "MarshalAsAttribute")
                        {
                            continue;
                        }
                        foreach (var named in attr.NamedArguments)
                        {
                            if (named.MemberName != "SizeConst")
                            {
                                continue;
                            }
                            size = (int)named.TypedValue.Value;
                        }
                    }

                    if (fieldType == "String")
                    {
                        // reader.Align(0x4, templatePosition);
                        var str = reader.ReadString(Encoding.UTF8, size, true);
                        field.SetValue(obj, str);
                    }
                    else
                    {
                        var str = reader.ReadBytes(size);
                        field.SetValue(obj, str);
                    }
                    break;

                case "Single":
                    reader.Align(4, 0);
                    field.SetValue(obj, reader.ReadSingle());
                    break;

                case "Boolean":
                    field.SetValue(obj, reader.ReadByte() != 0);
                    break;

                case "Int16":
                case "UInt16":
                    reader.Align(2, 0);
                    field.SetValue(obj, fieldType == "Int16" ? reader.ReadInt16() : (object)reader.ReadUInt16());
                    break;

                case "Int32":
                case "UInt32":
                    reader.Align(4, 0);
                    field.SetValue(obj, fieldType == "Int32" ? reader.ReadInt32() : (object)reader.ReadUInt32());
                    break;

                case "Int64":
                case "UInt64":
                    reader.Align(8, 0);
                    field.SetValue(obj, fieldType == "Int64" ? reader.ReadInt64() : (object)reader.ReadUInt64());
                    break;

                case "List`1":
                    reader.Align(8, 0);
                    if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(List <>))
                    {
                        Type itemType = field.FieldType.GetGenericArguments()[0];     // use this...
                        if (itemType == typeof(NMSTemplate))
                        {
                            field.SetValue(obj, DeserializeGenericList(reader, templatePosition));
                        }
                        else
                        {
                            // todo: get rid of this nastiness
                            MethodInfo method = typeof(NMSTemplate).GetMethod("DeserializeList", BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                                .MakeGenericMethod(new Type[] { itemType });
                            var list = method.Invoke(null, new object[] { reader, templatePosition });
                            field.SetValue(obj, list);
                        }
                    }

                    break;

                case "NMSTemplate":
                    reader.Align(8, 0);
                    long   startPos = reader.BaseStream.Position;
                    long   offset   = reader.ReadInt64();
                    string name     = reader.ReadString(Encoding.ASCII, 0x40, true);
                    long   endPos   = reader.BaseStream.Position;

                    if (offset != 0 && !String.IsNullOrEmpty(name))
                    {
                        reader.BaseStream.Position = startPos + offset;
                        NMSTemplate val = DeserializeBinaryTemplate(reader, name);
                        if (val == null)
                        {
                            throw new Exception("Failed to deserialize template " + name + "!");
                        }

                        field.SetValue(obj, val);
                    }
                    reader.BaseStream.Position = endPos;
                    break;

                default:
                    if (fieldType == "Colour")     // unsure if this is needed?
                    {
                        reader.Align(0x10, 0);
                    }
                    // todo: align for VariableSizeString?

                    var data = DeserializeBinaryTemplate(reader, fieldType);
                    if (data != null)
                    {
                        field.SetValue(obj, data);
                    }
                    break;
                }
            }

            return(obj);
        }
示例#5
0
        public static NMSTemplate DeserializeEXml(EXmlData xmlData)
        {
            NMSTemplate template       = TemplateFromName(xmlData.Template);
            Type        templateType   = template.GetType();
            var         templateFields = templateType.GetFields().OrderBy(field => field.MetadataToken); // hack to get fields in order of declaration (todo: use something less hacky, this might break mono?)

            foreach (var templateField in templateFields)
            {
                NMSAttribute settings = templateField.GetCustomAttribute <NMSAttribute>();
                if (settings == null)
                {
                    break;
                }
                if (settings.DefaultValue != null)
                {
                    templateField.SetValue(template, settings.DefaultValue);
                }
            }

            foreach (var xmlProperty in xmlData.Elements.OfType <EXmlProperty>())
            {
                FieldInfo    field     = templateType.GetField(xmlProperty.Name);
                Type         fieldType = field.FieldType;
                NMSAttribute settings  = field.GetCustomAttribute <NMSAttribute>();
                if (settings == null)
                {
                    settings = new NMSAttribute();
                }
                object fieldValue;
                switch (fieldType.Name)
                {
                case "String":
                    fieldValue = xmlProperty.Value;
                    break;

                case "Single":
                    fieldValue = float.Parse(xmlProperty.Value);
                    break;

                case "Boolean":
                    fieldValue = bool.Parse(xmlProperty.Value);
                    break;

                case "Int16":
                    fieldValue = short.Parse(xmlProperty.Value);
                    break;

                case "Int32":
                    var valuesMethod = templateType.GetMethod(field.Name + "Values");
                    if (valuesMethod != null)
                    {
                        if (String.IsNullOrEmpty(xmlProperty.Value))
                        {
                            fieldValue = (int)-1;
                        }
                        else
                        {
                            string[] values = (string[])valuesMethod.Invoke(template, null);
                            fieldValue = Array.FindIndex(values, v => v == xmlProperty.Value);
                        }
                    }
                    else if (settings.EnumValue != null)
                    {
                        if (String.IsNullOrEmpty(xmlProperty.Value))
                        {
                            fieldValue = (int)-1;
                        }
                        else
                        {
                            fieldValue = Array.FindIndex(settings.EnumValue, v => v == xmlProperty.Value);
                        }
                    }
                    else
                    {
                        fieldValue = int.Parse(xmlProperty.Value);
                    }
                    break;

                case "Int64":
                    fieldValue = long.Parse(xmlProperty.Value);
                    break;

                case "Byte[]":
                    fieldValue = xmlProperty.Value == null ? null : Convert.FromBase64String(xmlProperty.Value);
                    break;

                case "List`1":
                    Type  elementType = fieldType.GetGenericArguments()[0];
                    Type  listType    = typeof(List <>).MakeGenericType(elementType);
                    IList list        = (IList)Activator.CreateInstance(listType);
                    foreach (EXmlData innerXmlData in xmlProperty.Elements.OfType <EXmlData>())
                    {
                        NMSTemplate element = DeserializeEXml(innerXmlData);
                        list.Add(element);
                    }

                    fieldValue = list;
                    break;

                default:
                    if (field.FieldType.IsArray && field.FieldType.GetElementType().BaseType.Name == "NMSTemplate")
                    {
                        Array           array = Array.CreateInstance(field.FieldType.GetElementType(), settings.Size);
                        List <EXmlData> data  = xmlProperty.Elements.OfType <EXmlData>().ToList();
                        for (int i = 0; i < data.Count; ++i)
                        {
                            NMSTemplate element = DeserializeEXml(data[i]);
                            array.SetValue(element, i);
                        }

                        fieldValue = array;
                    }
                    else
                    {
                        fieldValue = fieldType.IsValueType ? Activator.CreateInstance(fieldType) : null;
                    }
                    break;
                }

                field.SetValue(template, fieldValue);
            }

            foreach (EXmlData innerXmlData in xmlData.Elements.OfType <EXmlData>())
            {
                FieldInfo   field         = templateType.GetField(innerXmlData.Name);
                NMSTemplate innerTemplate = DeserializeEXml(innerXmlData);
                field.SetValue(template, innerTemplate);
            }

            return(template);
        }