LSLib.Granny.GR2.GR2Reader.ReadStruct C# (CSharp) Method

ReadStruct() private method

private ReadStruct ( StructDefinition definition, MemberType memberType, object node, object parent ) : object
definition StructDefinition
memberType MemberType
node object
parent object
return object
        internal object ReadStruct(StructDefinition definition, MemberType memberType, object node, object parent)
        {
            var offset = (UInt32)Stream.Position;
            object cachedNode = null;
            if (memberType != MemberType.Inline && CachedStructs.TryGetValue(offset, out cachedNode))
            {
#if DEBUG_GR2_SERIALIZATION
                System.Console.WriteLine(String.Format("Skipped cached struct {1} at {0:X8}", offset, node.ToString()));
#endif
                Stream.Position += definition.Size(this);
                return cachedNode;
            }

            if (node != null)
            {
                // Don't save inline structs in the cached struct map, as they can occupy the same address as a non-inline struct
                // if they're at the beginning of said struct.
                // They also cannot be referenced from multiple locations, so caching them is of no use.
                if (memberType != MemberType.Inline)
                    CachedStructs.Add(offset, node);

#if DEBUG_GR2_FORMAT_DIFFERENCES
                // Create a struct definition from this instance and check if the GR2 type differs from the local type.
                var localDefn = new StructDefinition();
                localDefn.LoadFromType(node.GetType(), null);

                var localMembers = localDefn.Members.Where(m => m.ShouldSerialize(Header.tag)).ToList();
                var defnMembers = definition.Members.Where(m => m.ShouldSerialize(Header.tag)).ToList();

                if (localMembers.Count != defnMembers.Count)
                {
                    Trace.TraceWarning(String.Format("Struct {0} differs: Field count differs ({1} vs {2})", node.GetType().Name, localMembers.Count, defnMembers.Count));
                }
                else
                {
                    for (int i = 0; i < localMembers.Count; i++)
                    {
                        var member = localMembers[i];
                        var local = defnMembers[i];
                        if (member.Type != local.Type)
                        {
                            Trace.TraceWarning(String.Format(
                                "Struct {0}: Field {1} type differs ({1} vs {2})",
                                node.GetType().Name, local.Name, local.Type, member.Type
                            ));
                        }

                        if (!member.GrannyName.Equals(local.GrannyName))
                        {
                            Trace.TraceWarning(String.Format(
                                "Struct {0}: Field {1} name differs ({1} vs {2})",
                                node.GetType().Name, local.Name, local.GrannyName, member.GrannyName
                            ));
                        }

                        if (member.ArraySize != local.ArraySize)
                        {
                            Trace.TraceWarning(String.Format(
                                "Struct {0}: Field {1} array size differs ({1} vs {2})",
                                node.GetType().Name, local.Name, local.ArraySize, member.ArraySize
                            ));
                        }
                    }
                }
#endif

                definition.MapType(node);
                foreach (var member in definition.Members)
                {
                    var field = member.LookupFieldInfo(node);
                    if (field != null)
                    {
                        var value = ReadInstance(member, field.GetValue(node), field.FieldType, node);
                        field.SetValue(node, value);
                    }
                    else
                    {
                        ReadInstance(member, null, null, node);
                    }
                }
            }
            else
            {
                foreach (var member in definition.Members)
                {
                    ReadInstance(member, null, null, null);
                }
            }

            return node;
        }