示例#1
0
        private PropertyInfo ReadProperty(BinaryReader Reader, FPropertyTag Tag = null)
        {
            var Info = new PropertyInfo();

            if (Tag == null)
            {
                Info.Tag.Deserialize(Reader);
            }
            else
            {
                Info.Tag = Tag;
            }

            if (Info.Tag.Name == "None")
            {
                return(null);
            }

            if (Info.Tag.Size == 0)
            {
                return(Info);
            }

            if (Info.Tag.Type == "StructProperty")
            {
                if (!HardcodedStructs.ContainsKey(Info.Tag.StructName))
                {
                    // If it's not hardcoded it has tags for each field
                    for (var Child = ReadProperty(Reader); Child != null; Child = ReadProperty(Reader))
                    {
                        Info.Children.Add(Child);
                    }

                    return(Info);
                }

                Info.Prop = HardcodedStructs[Info.Tag.StructName]();
            }
            else if (Info.Tag.Type == "ArrayProperty")
            {
                var ArrayProp = new UArrayProperty();
                ArrayProp.Deserialize(Reader);
                Info.Prop = ArrayProp;

                for (var i = 0; i < ArrayProp.Length; i++)
                {
                    var Child = ReadProperty(Reader, ArrayProp.InnerTag);
                    Child.ArrayIndex = i;
                    Info.Children.Add(Child);
                }

                return(Info);
            }
            else
            {
                if (!PropertyConstructors.ContainsKey(Info.Tag.Type))
                {
                    // Unsupported type
                    Info.UnsupportedData = Reader.ReadBytes(Info.Tag.Size);
                    return(Info);
                }

                Info.Prop = PropertyConstructors[Info.Tag.Type]();
            }

            var Data = Reader.ReadBytes(Info.Tag.Size);

            using (var DataStream = new MemoryStream(Data))
            {
                using (var DataReader = new BinaryReader(DataStream))
                {
                    Info.Prop.Deserialize(DataReader);
                }
            }

            return(Info);
        }
        private PropertyInfo ReadProperty(BinaryReader Reader, FPropertyTag Tag = null)
        {
            var Info = new PropertyInfo();

            if (Tag == null)
            {
                Info.Tag.Deserialize(Reader);
            }
            else
            {
                Info.Tag = Tag;
            }

            if (Info.Tag.Name == "None")
            {
                return(null);
            }

            if (Info.Tag.Type == "BoolProperty")
            {
                // Special handling for tagless bools in MapProperty
                if (Tag != null)
                {
                    Info.Tag.BoolVal = Reader.ReadByte();
                }
                return(Info);
            }
            else if (Info.Tag.Type == "StructProperty")
            {
                if (Info.Tag.StructName == null || !HardcodedStructs.ContainsKey(Info.Tag.StructName))
                {
                    // If it's not hardcoded it has tags for each field
                    for (var Child = ReadProperty(Reader); Child != null; Child = ReadProperty(Reader))
                    {
                        Child.Parent = Info;
                        Info.Children.Add(Child);
                    }

                    return(Info);
                }

                Info.Prop = HardcodedStructs[Info.Tag.StructName]();
            }
            else if (Info.Tag.Type == "MapProperty")
            {
                var MapProp     = new UMapProperty();
                var StartOffset = Reader.BaseStream.Position;
                MapProp.Deserialize(Reader);
                Info.Prop = MapProp;

                for (var i = 0; i < MapProp.NumEntries; i++)
                {
                    var Key = ReadProperty(Reader, new FPropertyTag(Info.Tag.InnerType));
                    Key.ArrayIndex = i;
                    Key.KVType     = PropertyInfo.KeyValueType.Key;
                    Key.Parent     = Info;
                    Info.Children.Add(Key);

                    var Value = ReadProperty(Reader, new FPropertyTag(Info.Tag.ValueType));
                    Value.ArrayIndex = i;
                    Value.KVType     = PropertyInfo.KeyValueType.Value;
                    Value.Parent     = Info;
                    Info.Children.Add(Value);

                    if (Key.FailureReason != null || Value.FailureReason != null)
                    {
                        // It's impossible to skip a MapProperty child that can't be deserialized because the size is unknown
                        Reader.BaseStream.Seek(StartOffset, SeekOrigin.Begin);
                        Info.RawData       = Reader.ReadBytes(Info.Tag.Size);
                        Info.FailureReason = "Failed to deserialize child: " + (Key.FailureReason ?? Value.FailureReason);
                        Info.Children.Clear();
                        return(Info);
                    }
                }

                return(Info);
            }
            else if (Info.Tag.Type == "ArrayProperty")
            {
                var ArrayProp = new UArrayProperty();
                ArrayProp.Deserialize(Reader);
                Info.Prop = ArrayProp;

                for (var i = 0; i < ArrayProp.Length; i++)
                {
                    var Child = ReadProperty(Reader, ArrayProp.InnerTag);
                    Child.ArrayIndex = i;
                    Child.Parent     = Info;
                    Info.Children.Add(Child);
                }

                return(Info);
            }
            else
            {
                if (!PropertyConstructors.ContainsKey(Info.Tag.Type))
                {
                    Info.RawData       = Reader.ReadBytes(Info.Tag.Size);
                    Info.FailureReason = "Unsupported type";
                    return(Info);
                }

                Info.Prop = PropertyConstructors[Info.Tag.Type]();
            }

            // UMapProperty does not provide a full tag for the inner types, so the size is unknown
            if (Tag != null && Tag.Size == 0)
            {
                try
                {
                    Info.Prop.Deserialize(Reader);
                }
                catch (Exception e)
                {
                    // Treat it the same as an unsupported property type
                    Info.FailureReason = e.Message;
                    Info.Prop          = null;
                }

                return(Info);
            }

            Info.RawData = Reader.ReadBytes(Info.Tag.Size);
            using (var DataStream = new MemoryStream(Info.RawData))
            {
                using (var DataReader = new BinaryReader(DataStream))
                {
                    try
                    {
                        Info.Prop.Deserialize(DataReader);
                    }
                    catch (Exception e)
                    {
                        // Treat it the same as an unsupported property type
                        Info.FailureReason = e.Message;
                        Info.Prop          = null;
                    }
                }
            }

            return(Info);
        }