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; }
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); }