protected void TryReadInlineStandard(FieldGuessData output, BinaryReader reader)
        {
            if (output.IsInlineArray)
            {
                return;
            }
            long          beforePos = reader.BaseStream.Position;
            STUInlineInfo inline    = reader.Read <STUInlineInfo>();

            try {
                FieldGuessData[] inlineFields = GuessFields(InstanceFields[inline.FieldListIndex], reader);

                output.IsInlineStandard = true;
                output.InlineFields     = inlineFields;
            }
            catch (Exception) {
                output.IsInlineStandard = false;
            }

            reader.BaseStream.Position = beforePos;
        }
Exemple #2
0
        internal object InitializeObject(object instance, Type type, STUInstanceField[] writtenFields,
                                         BinaryReader reader)
        {
            Dictionary <uint, FieldInfo> fieldMap = CreateFieldMap(GetValidFields(type));

            uint?instanceChecksum = (Attribute.GetCustomAttribute(instance.GetType(), typeof(STUAttribute), false) as STUAttribute)?.Checksum;

            if (instance is STUInstance stuInstance && instanceChecksum != null)
            {
                stuInstance.InstanceChecksum = (uint)instanceChecksum;
            }

            foreach (STUInstanceField writtenField in writtenFields)
            {
                if (!fieldMap.ContainsKey(writtenField.FieldChecksum))
                {
                    Debugger.Log(0, "STU",
                                 $"[STU:{type}]: Unknown field {writtenField.FieldChecksum:X8} ({writtenField.FieldSize} bytes)\n");
                    if (writtenField.FieldSize == 0)
                    {
                        uint size = reader.ReadUInt32();
                        reader.BaseStream.Position += size;
                        continue;
                    }
                    reader.BaseStream.Position += writtenField.FieldSize;
                    continue;
                }
                FieldInfo         field   = fieldMap[writtenField.FieldChecksum];
                STUFieldAttribute element = field.GetCustomAttribute <STUFieldAttribute>() ?? new STUFieldAttribute();
                bool skip = false;
                if (element?.STUVersionOnly != null)
                {
                    skip = element.STUVersionOnly.All(version => version != Version);
                }
                if (element?.IgnoreVersion != null && skip)
                {
                    skip = !element.IgnoreVersion.Any(stufield => stufield == writtenField.FieldChecksum);
                }
                if (skip)
                {
                    continue;
                }
                if (!CheckCompatVersion(field, BuildVersion))
                {
                    continue;
                }
                if (field.FieldType.IsArray)
                {
                    field.SetValue(instance, InitializeObjectArray(writtenField, field.FieldType.GetElementType(), reader, element));
                }
                else
                {
                    if (writtenField.FieldSize == 0)
                    {
                        if (field.FieldType.IsClass || field.FieldType.IsValueType)
                        {
                            STUInlineInfo inline         = reader.Read <STUInlineInfo>();
                            object        inlineInstance = Activator.CreateInstance(field.FieldType);
                            if (inline.FieldListIndex < 0 || inline.FieldListIndex >= InstanceFields.Length)
                            {
                                continue;
                            }
                            field.SetValue(instance,
                                           InitializeObject(inlineInstance, field.FieldType, InstanceFields[inline.FieldListIndex],
                                                            reader));
                            STUInstance fieldInstance = field.GetValue(instance) as STUInstance;
                            if (fieldInstance != null)
                            {
                                fieldInstance.Usage = InstanceUsage.Inline;
                            }
                            HiddenInstances.Add(fieldInstance);
                            continue;
                        }
                    }
                    if (writtenField.FieldSize == 4 && field.FieldType.IsClass && !IsSimple(field.FieldType) && typeof(STUInstance).IsAssignableFrom(field.FieldType))
                    {
                        int instanceIndex = reader.ReadInt32();  // sometimes the inline isn't defined in the instance
                        EmbedRequests.Add(new KeyValuePair <object, FieldInfo>(instance, field), instanceIndex);
                        // this is embedded, don't initialise the class
                        continue;
                    }

                    reader.BaseStream.Position += element.Padding;

                    long position = -1;
                    if (element?.ReferenceValue == true)
                    {
                        long offset = reader.ReadInt64();
                        if (offset == 0)
                        {
                            continue;
                        }
                        position = reader.BaseStream.Position;
                        reader.BaseStream.Position = offset;
                    }
                    field.SetValue(instance, GetValue(instance, writtenField, field.FieldType, reader, element, field));
                    if (position > -1)
                    {
                        reader.BaseStream.Position = position;
                    }
                }
                if (element?.Verify != null)
                {
                    if (!field.GetValue(instance).Equals(element.Verify))
                    {
                        throw new Exception("Verification failed");
                    }
                }

                if (element.Demangle)
                {
                    DemangleInstance(instance, writtenField.FieldChecksum);
                }
            }

            return(instance);
        }