private static SequenceObjectInfo generateSequenceObjectInfo(int i, ME3Package pcc)
        {
            SequenceObjectInfo info = new SequenceObjectInfo();
            var inLinks             = pcc.Exports[i + 1].GetProperty <ArrayProperty <StructProperty> >("InputLinks");

            if (inLinks != null)
            {
                foreach (var seqOpInputLink in inLinks)
                {
                    info.inputLinks.Add(seqOpInputLink.GetProp <StrProperty>("LinkDesc").Value);
                }
            }
            return(info);
        }
        private static SequenceObjectInfo generateSequenceObjectInfo(int i, PCCObject pcc)
        {
            SequenceObjectInfo info = new SequenceObjectInfo();

            PropertyReader.Property inputLinks = PropertyReader.getPropOrNull(pcc, pcc.Exports[i + 1], "InputLinks");
            if (inputLinks != null)
            {
                int    pos    = 28;
                byte[] global = inputLinks.raw;
                int    count  = BitConverter.ToInt32(global, 24);
                for (int j = 0; j < count; j++)
                {
                    List <PropertyReader.Property> p2 = PropertyReader.ReadProp(pcc, global, pos);

                    info.inputLinks.Add(p2[0].Value.StringValue);
                    for (int k = 0; k < p2.Count(); k++)
                    {
                        pos += p2[k].raw.Length;
                    }
                }
            }
            return(info);
        }
        private static SequenceObjectInfo generateSequenceObjectInfo(int i, ME3Package pcc)
        {
            SequenceObjectInfo info = new SequenceObjectInfo();
            PropertyReader.Property inputLinks = PropertyReader.getPropOrNull(pcc.Exports[i + 1], "InputLinks");
            if (inputLinks != null)
            {
                int pos = 28;
                byte[] global = inputLinks.raw;
                int count = BitConverter.ToInt32(global, 24);
                for (int j = 0; j < count; j++)
                {
                    List<PropertyReader.Property> p2 = PropertyReader.ReadProp(pcc, global, pos);

                    info.inputLinks.Add(p2[0].Value.StringValue);
                    for (int k = 0; k < p2.Count(); k++)
                        pos += p2[k].raw.Length;
                }
            }
            return info;
        }
        //call this method to regenerate ME2ObjectInfo.json
        //Takes a long time (10 minutes maybe?). Application will be completely unresponsive during that time.
        public static void generateInfo()
        {
            var NewClasses         = new Dictionary <string, ClassInfo>();
            var NewStructs         = new Dictionary <string, ClassInfo>();
            var NewEnums           = new Dictionary <string, List <NameReference> >();
            var NewSequenceObjects = new Dictionary <string, SequenceObjectInfo>();

            foreach (string filePath in MELoadedFiles.GetOfficialFiles(MEGame.ME2))
            {
                if (Path.GetExtension(filePath) == ".pcc")
                {
                    using IMEPackage pcc = MEPackageHandler.OpenME2Package(filePath);
                    for (int j = 1; j <= pcc.ExportCount; j++)
                    {
                        ExportEntry exportEntry = pcc.GetUExport(j);
                        string      className   = exportEntry.ClassName;
                        if (className == "Enum")
                        {
                            generateEnumValues(exportEntry, NewEnums);
                        }
                        else if (className == "Class")
                        {
                            string objectName = exportEntry.ObjectName;
                            if (!NewClasses.ContainsKey(objectName))
                            {
                                NewClasses.Add(objectName, generateClassInfo(exportEntry));
                            }
                        }
                        else if (className == "ScriptStruct")
                        {
                            string objectName = exportEntry.ObjectName;
                            if (!NewStructs.ContainsKey(objectName))
                            {
                                NewStructs.Add(objectName, generateClassInfo(exportEntry, isStruct: true));
                            }
                        }
                        else if (exportEntry.IsOrInheritsFrom("SequenceObject"))
                        {
                            if (!NewSequenceObjects.TryGetValue(className, out SequenceObjectInfo seqObjInfo))
                            {
                                seqObjInfo = new SequenceObjectInfo();
                                NewSequenceObjects.Add(className, seqObjInfo);
                            }

                            int objInstanceVersion = exportEntry.GetProperty <IntProperty>("ObjInstanceVersion");
                            if (objInstanceVersion > seqObjInfo.ObjInstanceVersion)
                            {
                                seqObjInfo.ObjInstanceVersion = objInstanceVersion;
                            }
                        }
                    }
                    //Debug.WriteLine("Releasing " + pcc.FileName);
                }
            }

            //CUSTOM ADDITIONS
            try
            {
                NewClasses.Add("LightMapTexture2D", new ClassInfo
                {
                    baseClass   = "Texture2D",
                    exportIndex = 0,
                    pccPath     = UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName
                });

                NewClasses["StaticMesh"] = new ClassInfo
                {
                    baseClass   = "Object",
                    exportIndex = 0,
                    pccPath     = UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName,
                    properties  =
                    {
                        new KeyValuePair <string, PropertyInfo>("UseSimpleRigidBodyCollision", new PropertyInfo(PropertyType.BoolProperty)),
                        new KeyValuePair <string, PropertyInfo>("UseSimpleLineCollision",      new PropertyInfo(PropertyType.BoolProperty)),
                        new KeyValuePair <string, PropertyInfo>("UseSimpleBoxCollision",       new PropertyInfo(PropertyType.BoolProperty)),
                        new KeyValuePair <string, PropertyInfo>("UseFullPrecisionUVs",         new PropertyInfo(PropertyType.BoolProperty)),
                        new KeyValuePair <string, PropertyInfo>("BodySetup",                   new PropertyInfo(PropertyType.ObjectProperty, "RB_BodySetup")),
                        new KeyValuePair <string, PropertyInfo>("LODDistanceRatio",            new PropertyInfo(PropertyType.FloatProperty)),
                        new KeyValuePair <string, PropertyInfo>("LightMapCoordinateIndex",     new PropertyInfo(PropertyType.IntProperty)),
                        new KeyValuePair <string, PropertyInfo>("LightMapResolution",          new PropertyInfo(PropertyType.IntProperty)),
                    }
                };
            }
            catch (Exception)
            {
            }

            //SFXPhysicalMaterialDecals missing items
            ClassInfo sfxpmd = NewClasses["SFXPhysicalMaterialDecals"];

            string[] decalComponentArrays = { "HeavyPistol", "AutoPistol", "HandCannon", "SMG", "Shotgun", "HeavyShotgun", "FlakGun", "AssaultRifle", "Needler", "Machinegun", "SniperRifle", "AntiMatRifle", "MassCannon", "ParticleBeam" };
            foreach (string decal in decalComponentArrays)
            {
                sfxpmd.properties.Add(decal, new PropertyInfo(PropertyType.ArrayProperty, "DecalComponent"));
            }

            NewClasses["SFXWeapon"].properties.Add("InstantHitDamageTypes", new PropertyInfo(PropertyType.ArrayProperty, "Class"));

            File.WriteAllText(jsonPath, JsonConvert.SerializeObject(new { SequenceObjects = NewSequenceObjects, Classes = NewClasses, Structs = NewStructs, Enums = NewEnums }, Formatting.Indented));
        }
        //call this method to regenerate ME1ObjectInfo.json
        //Takes a long time (10 to 20 minutes maybe?). Application will be completely unresponsive during that time.
        public static void generateInfo()
        {
            Classes         = new Dictionary <string, ClassInfo>();
            Structs         = new Dictionary <string, ClassInfo>();
            Enums           = new Dictionary <string, List <NameReference> >();
            SequenceObjects = new Dictionary <string, SequenceObjectInfo>();
            foreach (string file in MELoadedFiles.GetOfficialFiles(MEGame.ME1))
            {
                if (Path.GetExtension(file) == ".upk" || Path.GetExtension(file) == ".sfm" || Path.GetExtension(file) == ".u")
                {
                    Debug.WriteLine($"File: {file}");
                    using IMEPackage pcc = MEPackageHandler.OpenME1Package(file);
                    for (int j = 1; j <= pcc.ExportCount; j++)
                    {
                        ExportEntry exportEntry = pcc.GetUExport(j);
                        string      className   = exportEntry.ClassName;
                        if (className == "Enum")
                        {
                            generateEnumValues(exportEntry);
                        }
                        else if (className == "Class")
                        {
                            string objectName = exportEntry.ObjectName;
                            Debug.WriteLine($"Generating information for {objectName}");
                            if (!Classes.ContainsKey(objectName))
                            {
                                Classes.Add(objectName, generateClassInfo(exportEntry));
                            }
                        }
                        else if (className == "ScriptStruct")
                        {
                            string objectName = exportEntry.ObjectName;
                            if (!Structs.ContainsKey(exportEntry.ObjectName))
                            {
                                Structs.Add(objectName, generateClassInfo(exportEntry, isStruct: true));
                            }
                        }
                        else if (exportEntry.IsOrInheritsFrom("SequenceObject"))
                        {
                            if (!SequenceObjects.TryGetValue(className, out SequenceObjectInfo seqObjInfo))
                            {
                                seqObjInfo = new SequenceObjectInfo();
                                SequenceObjects.Add(className, seqObjInfo);
                            }

                            int objInstanceVersion = exportEntry.GetProperty <IntProperty>("ObjInstanceVersion");
                            if (objInstanceVersion > seqObjInfo.ObjInstanceVersion)
                            {
                                seqObjInfo.ObjInstanceVersion = objInstanceVersion;
                            }
                        }
                    }
                }
            }

            //CUSTOM ADDITIONS
            Classes["LightMapTexture2D"] = new ClassInfo
            {
                baseClass   = "Texture2D",
                exportIndex = 0,
                pccPath     = UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName
            };

            Classes["StaticMesh"] = new ClassInfo
            {
                baseClass   = "Object",
                exportIndex = 0,
                pccPath     = UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName,
                properties  =
                {
                    new KeyValuePair <string, PropertyInfo>("UseSimpleRigidBodyCollision",   new PropertyInfo(PropertyType.BoolProperty)),
                    new KeyValuePair <string, PropertyInfo>("UseSimpleLineCollision",        new PropertyInfo(PropertyType.BoolProperty)),
                    new KeyValuePair <string, PropertyInfo>("UseSimpleBoxCollision",         new PropertyInfo(PropertyType.BoolProperty)),
                    new KeyValuePair <string, PropertyInfo>("ForceDoubleSidedShadowVolumes", new PropertyInfo(PropertyType.BoolProperty)),
                    new KeyValuePair <string, PropertyInfo>("BodySetup",                     new PropertyInfo(PropertyType.ObjectProperty, "RB_BodySetup")),
                    new KeyValuePair <string, PropertyInfo>("LODDistanceRatio",              new PropertyInfo(PropertyType.FloatProperty)),
                    new KeyValuePair <string, PropertyInfo>("LightMapCoordinateIndex",       new PropertyInfo(PropertyType.IntProperty)),
                    new KeyValuePair <string, PropertyInfo>("LightMapResolution",            new PropertyInfo(PropertyType.IntProperty)),
                    new KeyValuePair <string, PropertyInfo>("SoundCue",                      new PropertyInfo(PropertyType.ObjectProperty, "SoundCue")),
                }
            };


            File.WriteAllText(jsonPath, JsonConvert.SerializeObject(new { SequenceObjects, Classes, Structs, Enums }, Formatting.Indented));
        }