Exemplo n.º 1
0
        private string getEnclosingType(TreeNode node)
        {
            Stack <TreeNode> nodeStack = new Stack <TreeNode>();
            string           typeName  = className;
            string           propname;

            UnrealObjectInfo.PropertyInfo p;
            while (node != null && !node.Tag.Equals(nodeType.Root))
            {
                nodeStack.Push(node);
                node = node.Parent;
            }
            bool isStruct = false;

            while (nodeStack.Count > 0)
            {
                node = nodeStack.Pop();
                if ((nodeType)node.Tag == nodeType.ArrayLeafStruct)
                {
                    continue;
                }
                propname = pcc.getNameEntry(BitConverter.ToInt32(memory, Math.Abs(Convert.ToInt32(node.Name))));
                p        = UnrealObjectInfo.getPropertyInfo(typeName, propname, isStruct);
                typeName = p.reference;
                isStruct = true;
            }
            return(typeName);
        }
        public static void ImportProperty(PCCObject pcc, PCCObject importpcc, Property p, string className, System.IO.MemoryStream m, bool inStruct = false)
        {
            string name    = importpcc.getNameEntry(p.Name);
            int    idxname = pcc.FindNameOrAdd(name);

            m.Write(BitConverter.GetBytes(idxname), 0, 4);
            m.Write(new byte[4], 0, 4);
            if (name == "None")
            {
                return;
            }
            string type    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 8));
            int    idxtype = pcc.FindNameOrAdd(type);

            m.Write(BitConverter.GetBytes(idxtype), 0, 4);
            m.Write(new byte[4], 0, 4);
            string          name2;
            int             idxname2;
            int             size, count, pos;
            List <Property> Props;

            switch (type)
            {
            case "IntProperty":
            case "FloatProperty":
            case "ObjectProperty":
            case "StringRefProperty":
                m.Write(BitConverter.GetBytes(4), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(p.Value.IntValue), 0, 4);
                break;

            case "NameProperty":
                m.Write(BitConverter.GetBytes(8), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                //preserve index or whatever the second part of a namereference is
                m.Write(p.raw, 28, 4);
                break;

            case "BoolProperty":
                m.Write(new byte[8], 0, 8);
                m.WriteByte((byte)p.Value.IntValue);
                break;

            case "BioMask4Property":
                m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.WriteByte((byte)p.Value.IntValue);
                break;

            case "ByteProperty":
                name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                idxname2 = pcc.FindNameOrAdd(name2);
                m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                m.Write(new byte[4], 0, 4);
                if (p.Size == 8)
                {
                    m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                else
                {
                    m.WriteByte(p.raw[32]);
                }
                break;

            case "DelegateProperty":
                size = BitConverter.ToInt32(p.raw, 16);
                if (size == 0xC)
                {
                    name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28));
                    idxname2 = pcc.FindNameOrAdd(name2);
                    m.Write(BitConverter.GetBytes(0xC), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                else
                {
                    m.Write(BitConverter.GetBytes(size), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    for (int i = 0; i < size; i++)
                    {
                        m.WriteByte(p.raw[24 + i]);
                    }
                }
                break;

            case "StrProperty":
                name2 = p.Value.StringValue;
                m.Write(BitConverter.GetBytes(4 + name2.Length * 2), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(-name2.Length), 0, 4);
                foreach (char c in name2)
                {
                    m.WriteByte((byte)c);
                    m.WriteByte(0);
                }
                break;

            case "StructProperty":
                size     = BitConverter.ToInt32(p.raw, 16);
                name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                idxname2 = pcc.FindNameOrAdd(name2);
                pos      = 32;
                Props    = new List <Property>();
                try
                {
                    Props = ReadProp(importpcc, p.raw, pos);
                }
                catch (Exception)
                {
                }
                m.Write(BitConverter.GetBytes(size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                m.Write(new byte[4], 0, 4);
                if (Props.Count == 0 || Props[0].TypeVal == Type.Unknown)
                {
                    for (int i = 0; i < size; i++)
                    {
                        m.WriteByte(p.raw[32 + i]);
                    }
                }
                else
                {
                    foreach (Property pp in Props)
                    {
                        ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                }
                break;

            case "ArrayProperty":
                size  = BitConverter.ToInt32(p.raw, 16);
                count = BitConverter.ToInt32(p.raw, 24);
                UnrealObjectInfo.PropertyInfo info      = UnrealObjectInfo.getPropertyInfo(className, name, inStruct);
                UnrealObjectInfo.ArrayType    arrayType = UnrealObjectInfo.getArrayType(info);
                pos = 28;
                List <Property> AllProps = new List <Property>();

                if (arrayType == UnrealObjectInfo.ArrayType.Struct)
                {
                    for (int i = 0; i < count; i++)
                    {
                        Props = new List <Property>();
                        try
                        {
                            Props = ReadProp(importpcc, p.raw, pos);
                        }
                        catch (Exception)
                        {
                        }
                        AllProps.AddRange(Props);
                        if (Props.Count != 0)
                        {
                            pos = Props[Props.Count - 1].offend;
                        }
                    }
                }
                m.Write(BitConverter.GetBytes(size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(count), 0, 4);
                if (AllProps.Count != 0 && (info == null || !UnrealObjectInfo.isImmutable(info.reference)))
                {
                    foreach (Property pp in AllProps)
                    {
                        ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                }
                else if (arrayType == UnrealObjectInfo.ArrayType.Name)
                {
                    for (int i = 0; i < count; i++)
                    {
                        string s = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28 + i * 8));
                        m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(s)), 0, 4);
                        //preserve index or whatever the second part of a namereference is
                        m.Write(p.raw, 32 + i * 8, 4);
                    }
                }
                else
                {
                    m.Write(p.raw, 28, size - 4);
                }
                break;

            default:
                throw new Exception(type);
            }
        }
Exemplo n.º 3
0
        private int GenerateSpecialStructProp(TreeNode t, string s, int pos, PropertyReader.Property prop)
        {
            if (pos > memory.Length)
            {
                throw new Exception(": tried to read past bounds of Export Data");
            }
            int      n;
            TreeNode node;

            UnrealObjectInfo.PropertyInfo propInfo;
            switch (prop.TypeVal)
            {
            case PropertyReader.Type.FloatProperty:
                s        += BitConverter.ToSingle(memory, pos).ToString("0.0######");
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafFloat;
                t.Nodes.Add(node);
                pos += 4;
                break;

            case PropertyReader.Type.IntProperty:
                s        += BitConverter.ToInt32(memory, pos).ToString();
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafInt;
                t.Nodes.Add(node);
                pos += 4;
                break;

            case PropertyReader.Type.ObjectProperty:
                n         = BitConverter.ToInt32(memory, pos);
                s        += n + " (" + pcc.getObjectName(n) + ")";
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafObject;
                t.Nodes.Add(node);
                pos += 4;
                break;

            case PropertyReader.Type.StringRefProperty:
                n         = BitConverter.ToInt32(memory, pos);
                s        += "#" + n + ": ";
                s        += TalkFiles.tlkList.Count == 0 ? "(.tlk not loaded)" : TalkFiles.findDataById(n);
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafInt;
                t.Nodes.Add(node);
                pos += 4;
                break;

            case PropertyReader.Type.NameProperty:
                n         = BitConverter.ToInt32(memory, pos);
                pos      += 4;
                s        += "\"" + pcc.getNameEntry(n) + "\"_" + BitConverter.ToInt32(memory, pos);
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafName;
                t.Nodes.Add(node);
                pos += 4;
                break;

            case PropertyReader.Type.BoolProperty:
                s        += (memory[pos] > 0).ToString();
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafBool;
                t.Nodes.Add(node);
                pos += 1;
                break;

            case PropertyReader.Type.ByteProperty:
                if (prop.Size != 1)
                {
                    string enumName = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(prop.Name))?.reference;
                    if (enumName != null)
                    {
                        s += "\"" + enumName + "\", ";
                    }
                    s        += "\"" + pcc.getNameEntry(BitConverter.ToInt32(memory, pos)) + "\"";
                    node      = new TreeNode(s);
                    node.Name = pos.ToString();
                    node.Tag  = nodeType.StructLeafEnum;
                    t.Nodes.Add(node);
                    pos += 8;
                }
                else
                {
                    s        += "(byte)" + memory[pos].ToString();
                    node      = new TreeNode(s);
                    node.Name = pos.ToString();
                    node.Tag  = nodeType.StructLeafByte;
                    t.Nodes.Add(node);
                    pos += 1;
                }
                break;

            case PropertyReader.Type.StrProperty:
                n    = BitConverter.ToInt32(memory, pos);
                pos += 4;
                s   += "\"";
                for (int i = 0; i < n - 1; i++)
                {
                    s += (char)memory[pos + i * 2];
                }
                s        += "\"";
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafStr;
                t.Nodes.Add(node);
                pos += n * 2;
                break;

            case PropertyReader.Type.ArrayProperty:
                n         = BitConverter.ToInt32(memory, pos);
                s        += n + " elements";
                node      = new TreeNode(s);
                node.Name = pos.ToString();
                node.Tag  = nodeType.StructLeafArray;
                pos      += 4;
                propInfo  = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(prop.Name));
                UnrealObjectInfo.ArrayType arrayType = UnrealObjectInfo.getArrayType(propInfo);
                TreeNode node2;
                string   s2;
                for (int i = 0; i < n; i++)
                {
                    if (arrayType == UnrealObjectInfo.ArrayType.Struct)
                    {
                        readerpos  = pos;
                        node2      = new TreeNode(i + ": (" + propInfo.reference + ")");
                        node2.Name = (-pos).ToString();
                        node2.Tag  = nodeType.StructLeafStruct;
                        GenerateSpecialStruct(node2, propInfo.reference, 0);
                        node.Nodes.Add(node2);
                        pos = readerpos;
                    }
                    else
                    {
                        s2 = "";
                        PropertyReader.Type type = PropertyReader.Type.None;
                        int size = 0;
                        switch (arrayType)
                        {
                        case UnrealObjectInfo.ArrayType.Object:
                            type = PropertyReader.Type.ObjectProperty;
                            break;

                        case UnrealObjectInfo.ArrayType.Name:
                            type = PropertyReader.Type.NameProperty;
                            break;

                        case UnrealObjectInfo.ArrayType.Byte:
                            type = PropertyReader.Type.ByteProperty;
                            size = 1;
                            break;

                        case UnrealObjectInfo.ArrayType.Enum:
                            type = PropertyReader.Type.ByteProperty;
                            break;

                        case UnrealObjectInfo.ArrayType.Bool:
                            type = PropertyReader.Type.BoolProperty;
                            break;

                        case UnrealObjectInfo.ArrayType.String:
                            type = PropertyReader.Type.StrProperty;
                            break;

                        case UnrealObjectInfo.ArrayType.Float:
                            type = PropertyReader.Type.FloatProperty;
                            break;

                        case UnrealObjectInfo.ArrayType.Int:
                            type = PropertyReader.Type.IntProperty;
                            break;
                        }
                        pos = GenerateSpecialStructProp(node, s2, pos, new PropertyReader.Property {
                            TypeVal = type, Size = size
                        });
                    }
                }
                t.Nodes.Add(node);
                break;

            case PropertyReader.Type.StructProperty:
                propInfo  = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(prop.Name));
                s        += propInfo.reference;
                node      = new TreeNode(s);
                node.Name = (-pos).ToString();
                node.Tag  = nodeType.StructLeafStruct;
                readerpos = pos;
                GenerateSpecialStruct(node, propInfo.reference, 0);
                pos = readerpos;
                t.Nodes.Add(node);
                break;

            case PropertyReader.Type.DelegateProperty:
                throw new NotImplementedException($"at position {pos.ToString("X4")}: cannot read Delegate property of Immutable struct");

            case PropertyReader.Type.Unknown:
                throw new NotImplementedException($"at position {pos.ToString("X4")}: cannot read Unkown property of Immutable struct");

            case PropertyReader.Type.None:
            default:
                break;
            }

            return(pos);
        }
Exemplo n.º 4
0
        //structs that are serialized down to just their values.
        private void GenerateSpecialStruct(TreeNode t, string structType, int size)
        {
            TreeNode node;

            //have to handle this specially to get the degrees conversion
            if (structType == "Rotator")
            {
                string[] labels = { "Pitch", "Yaw", "Roll" };
                int      val;
                for (int i = 0; i < 3; i++)
                {
                    val       = BitConverter.ToInt32(memory, readerpos);
                    node      = new TreeNode(readerpos.ToString("X4") + ": " + labels[i] + " : " + val + " (" + ((float)val * 360f / 65536f).ToString("0.0######") + " degrees)");
                    node.Name = readerpos.ToString();
                    node.Tag  = nodeType.StructLeafDeg;
                    t.Nodes.Add(node);
                    readerpos += 4;
                }
            }
            else
            {
                if (UnrealObjectInfo.Structs.ContainsKey(structType))
                {
                    List <PropertyReader.Property> props;
                    //memoize
                    if (defaultStructValues.ContainsKey(structType))
                    {
                        props = defaultStructValues[structType];
                    }
                    else
                    {
                        byte[] defaultValue = UnrealObjectInfo.getDefaultClassValue(pcc, structType, true);
                        if (defaultValue == null)
                        {
                            //just prints the raw hex since there's no telling what it actually is
                            node     = new TreeNode(readerpos.ToString("X4") + ": " + memory.Skip(readerpos).Take(size).Aggregate("", (b, s) => b + " " + s.ToString("X2")));
                            node.Tag = nodeType.Unknown;
                            t.Nodes.Add(node);
                            readerpos += size;
                            return;
                        }
                        props = PropertyReader.ReadProp(pcc, defaultValue, 0);
                        defaultStructValues.Add(structType, props);
                    }
                    for (int i = 0; i < props.Count; i++)
                    {
                        string s = readerpos.ToString("X4") + ": " + pcc.getNameEntry(props[i].Name) + " : ";
                        readerpos = GenerateSpecialStructProp(t, s, readerpos, props[i]);
                    }
                }
            }

            #region Old method
            //if (structType == "Vector2d" || structType == "RwVector2")
            //{
            //    string[] labels = { "X", "Y" };
            //    for (int i = 0; i < 2; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + BitConverter.ToSingle(memory, pos).ToString("0.0######"));
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafFloat;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            //else if (structType == "Vector" || structType == "RwVector3")
            //{
            //    string[] labels = { "X", "Y", "Z" };
            //    for (int i = 0; i < 3; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + BitConverter.ToSingle(memory, pos).ToString("0.0######"));
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafFloat;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            //else if (structType == "Rotator")
            //{
            //    string[] labels = { "Pitch", "Yaw", "Roll" };
            //    int val;
            //    for (int i = 0; i < 3; i++)
            //    {
            //        val = BitConverter.ToInt32(memory, pos);
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + val + " (" + ((float)val * 360f / 65536f).ToString("0.0######") + " degrees)");
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafDeg;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            //else if (structType == "Color")
            //{
            //    string[] labels = { "B", "G", "R", "A" };
            //    for (int i = 0; i < 4; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + memory[pos]);
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafByte;
            //        t.Nodes.Add(node);
            //        pos += 1;
            //    }
            //}
            //else if (structType == "LinearColor")
            //{
            //    string[] labels = { "R", "G", "B", "A" };
            //    for (int i = 0; i < 4; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + BitConverter.ToSingle(memory, pos).ToString("0.0######"));
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafFloat;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            ////uses EndsWith to support RwQuat, RwVector4, and RwPlane
            //else if (structType.EndsWith("Quat") || structType.EndsWith("Vector4") || structType.EndsWith("Plane"))
            //{
            //    string[] labels = { "X", "Y", "Z", "W" };
            //    for (int i = 0; i < 4; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + BitConverter.ToSingle(memory, pos).ToString("0.0######"));
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafFloat;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            //else if (structType == "TwoVectors")
            //{
            //    string[] labels = { "X", "Y", "Z", "X", "Y", "Z" };
            //    for (int i = 0; i < 6; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + BitConverter.ToSingle(memory, pos).ToString("0.0######"));
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafFloat;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            //else if (structType == "Matrix" || structType == "RwMatrix44")
            //{
            //    string[] labels = { "X Plane", "Y Plane", "Z Plane", "W Plane" };
            //    string[] labels2 = { "X", "Y", "Z", "W" };
            //    TreeNode node2;
            //    for (int i = 0; i < 3; i++)
            //    {
            //        node2 = new TreeNode(labels[i]);
            //        node2.Name = pos.ToString();
            //        for (int j = 0; j < 4; j++)
            //        {
            //            node = new TreeNode(pos.ToString("X4") + ": " + labels2[j] + " : " + BitConverter.ToSingle(memory, pos).ToString("0.0######"));
            //            node.Name = pos.ToString();
            //            node.Tag = nodeType.StructLeafFloat;
            //            node2.Nodes.Add(node);
            //            pos += 4;
            //        }
            //        t.Nodes.Add(node2);
            //    }
            //}
            //else if (structType == "Guid")
            //{
            //    string[] labels = { "A", "B", "C", "D" };
            //    for (int i = 0; i < 4; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + BitConverter.ToInt32(memory, pos));
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafInt;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            //else if (structType == "IntPoint")
            //{
            //    string[] labels = { "X", "Y" };
            //    for (int i = 0; i < 2; i++)
            //    {
            //        node = new TreeNode(pos.ToString("X4") + ": " + labels[i] + " : " + BitConverter.ToInt32(memory, pos));
            //        node.Name = pos.ToString();
            //        node.Tag = nodeType.StructLeafInt;
            //        t.Nodes.Add(node);
            //        pos += 4;
            //    }
            //}
            //else if (structType == "Box" || structType == "BioRwBox")
            //{
            //    string[] labels = { "Min", "Max" };
            //    string[] labels2 = { "X", "Y", "Z" };
            //    TreeNode node2;
            //    for (int i = 0; i < 2; i++)
            //    {
            //        node2 = new TreeNode(labels[i]);
            //        node2.Name = pos.ToString();
            //        for (int j = 0; j < 3; j++)
            //        {
            //            node = new TreeNode(pos.ToString("X4") + ": " + labels2[j] + " : " + BitConverter.ToSingle(memory, pos).ToString("0.0######"));
            //            node.Name = pos.ToString();
            //            node.Tag = nodeType.StructLeafFloat;
            //            node2.Nodes.Add(node);
            //            pos += 4;
            //        }
            //        t.Nodes.Add(node2);
            //    }
            //    node = new TreeNode(pos.ToString("X4") + ": IsValid : " + memory[pos]);
            //    node.Name = pos.ToString();
            //    node.Tag = nodeType.StructLeafByte;
            //    t.Nodes.Add(node);
            //    pos += 1;
            //}
            //else
            //{
            //    for (int i = 0; i < size / 4; i++)
            //    {
            //        int val = BitConverter.ToInt32(memory, pos);
            //        string s = pos.ToString("X4") + ": " + val.ToString();
            //        t.Nodes.Add(s);
            //        pos += 4;
            //    }
            //}
            //readerpos = pos;
            #endregion
        }
Exemplo n.º 5
0
 public void GenerateTree(TreeNode localRoot, List <PropHeader> headersList)
 {
     foreach (PropHeader header in headersList)
     {
         if (readerpos > memory.Length)
         {
             throw new IndexOutOfRangeException(": tried to read past bounds of Export Data");
         }
         nodeType type = getType(pcc.getNameEntry(header.type));
         if (type != nodeType.ArrayProperty && type != nodeType.StructProperty)
         {
             localRoot.Nodes.Add(GenerateNode(header));
         }
         else
         {
             if (type == nodeType.ArrayProperty)
             {
                 TreeNode t           = GenerateNode(header);
                 int      arrayLength = BitConverter.ToInt32(memory, header.offset + 24);
                 readerpos = header.offset + 28;
                 int tmp = readerpos;
                 UnrealObjectInfo.ArrayType arrayType;
                 try
                 {
                     arrayType = UnrealObjectInfo.getArrayType(className, pcc.getNameEntry(header.name));
                 }
                 catch (Exception)
                 {
                     arrayType = UnrealObjectInfo.ArrayType.Int;
                 }
                 if (arrayType == UnrealObjectInfo.ArrayType.Struct)
                 {
                     UnrealObjectInfo.PropertyInfo info = UnrealObjectInfo.getPropertyInfo(className, pcc.getNameEntry(header.name));
                     t.Text = t.Text.Insert(t.Text.IndexOf("Size: ") - 2, $"({info.reference})");
                     for (int i = 0; i < arrayLength; i++)
                     {
                         readerpos = tmp;
                         int pos = tmp;
                         List <PropHeader> arrayListPropHeaders = ReadHeadersTillNone();
                         tmp = readerpos;
                         TreeNode n = new TreeNode(i.ToString());
                         n.Tag  = nodeType.ArrayLeafStruct;
                         n.Name = (-pos).ToString();
                         t.Nodes.Add(n);
                         n = t.LastNode;
                         if (info != null && (UnrealObjectInfo.isImmutable(info.reference) || arrayListPropHeaders.Count == 0))
                         {
                             readerpos = pos;
                             GenerateSpecialStruct(n, info.reference, header.size / arrayLength);
                             tmp = readerpos;
                         }
                         else if (arrayListPropHeaders.Count > 0)
                         {
                             GenerateTree(n, arrayListPropHeaders);
                         }
                         else
                         {
                             throw new Exception($"at position {readerpos.ToString("X4")}. Could not read element {i} of ArrayProperty {pcc.getNameEntry(header.name)}");
                         }
                         t.LastNode.Remove();
                         t.Nodes.Add(n);
                     }
                     localRoot.Nodes.Add(t);
                 }
                 else
                 {
                     t.Text = t.Text.Insert(t.Text.IndexOf("Size: ") - 2, $"({arrayType.ToString()})");
                     int count = 0;
                     int pos;
                     for (int i = 0; i < (header.size - 4); count++)
                     {
                         pos = header.offset + 28 + i;
                         if (pos > memory.Length)
                         {
                             throw new Exception(": tried to read past bounds of Export Data");
                         }
                         int      val  = BitConverter.ToInt32(memory, pos);
                         string   s    = pos.ToString("X4") + "|" + count + ": ";
                         TreeNode node = new TreeNode();
                         node.Name = pos.ToString();
                         if (arrayType == UnrealObjectInfo.ArrayType.Object)
                         {
                             node.Tag = nodeType.ArrayLeafObject;
                             int value = val;
                             if (value == 0)
                             {
                                 //invalid
                                 s += "Null [" + value + "] ";
                             }
                             else
                             {
                                 bool isImport = value < 0;
                                 if (isImport)
                                 {
                                     value = -value;
                                 }
                                 value--; //0-indexed
                                 if (isImport)
                                 {
                                     if (pcc.Imports.Count > value)
                                     {
                                         s += pcc.Imports[value].PackageFullName + "." + pcc.Imports[value].ObjectName + " [IMPORT " + value + "]";
                                     }
                                     else
                                     {
                                         s += "Index not in import list [" + value + "]";
                                     }
                                 }
                                 else
                                 {
                                     if (pcc.Exports.Count > value)
                                     {
                                         s += pcc.Exports[value].PackageFullName + "." + pcc.Exports[value].ObjectName + " [EXPORT " + value + "]";
                                     }
                                     else
                                     {
                                         s += "Index not in export list [" + value + "]";
                                     }
                                 }
                             }
                             i += 4;
                         }
                         else if (arrayType == UnrealObjectInfo.ArrayType.Name || arrayType == UnrealObjectInfo.ArrayType.Enum)
                         {
                             node.Tag = arrayType == UnrealObjectInfo.ArrayType.Name ? nodeType.ArrayLeafName : nodeType.ArrayLeafEnum;
                             int value = val;
                             if (value < 0)
                             {
                                 s += "Invalid Name Index [" + value + "]";
                             }
                             else
                             {
                                 if (pcc.Names.Count > value)
                                 {
                                     s += $"\"{pcc.Names[value]}\"_{BitConverter.ToInt32(memory, pos + 4)}[NAMEINDEX {value}]";
                                 }
                                 else
                                 {
                                     s += "Index not in name list [" + value + "]";
                                 }
                             }
                             i += 8;
                         }
                         else if (arrayType == UnrealObjectInfo.ArrayType.Float)
                         {
                             node.Tag = nodeType.ArrayLeafFloat;
                             s       += BitConverter.ToSingle(memory, pos).ToString("0.0######");
                             i       += 4;
                         }
                         else if (arrayType == UnrealObjectInfo.ArrayType.Byte)
                         {
                             node.Tag = nodeType.ArrayLeafByte;
                             s       += "(byte)" + memory[pos];
                             i       += 1;
                         }
                         else if (arrayType == UnrealObjectInfo.ArrayType.Bool)
                         {
                             node.Tag = nodeType.ArrayLeafBool;
                             s       += BitConverter.ToBoolean(memory, pos);
                             i       += 1;
                         }
                         else if (arrayType == UnrealObjectInfo.ArrayType.String)
                         {
                             node.Tag = nodeType.ArrayLeafString;
                             int sPos = pos + 4;
                             s += "\"";
                             int len = val > 0 ? val : -val;
                             for (int j = 1; j < len; j++)
                             {
                                 s    += BitConverter.ToChar(memory, sPos);
                                 sPos += 2;
                             }
                             s += "\"";
                             i += (len * 2) + 4;
                         }
                         else
                         {
                             node.Tag = nodeType.ArrayLeafInt;
                             s       += val.ToString();
                             i       += 4;
                         }
                         node.Text = s;
                         t.Nodes.Add(node);
                     }
                     localRoot.Nodes.Add(t);
                 }
             }
             if (type == nodeType.StructProperty)
             {
                 TreeNode t = GenerateNode(header);
                 readerpos = header.offset + 32;
                 List <PropHeader> ll = ReadHeadersTillNone();
                 if (ll.Count != 0)
                 {
                     GenerateTree(t, ll);
                 }
                 else
                 {
                     string structType = pcc.getNameEntry(BitConverter.ToInt32(memory, header.offset + 24));
                     GenerateSpecialStruct(t, structType, header.size);
                 }
                 localRoot.Nodes.Add(t);
             }
         }
     }
 }