Exemple #1
0
        public static PropertyCollection getDefaultStructValue(string className, bool stripTransients)
        {
            bool isImmutable = UnrealObjectInfo.IsImmutable(className, MEGame.ME1);

            if (Structs.ContainsKey(className))
            {
                ClassInfo info = Structs[className];
                try
                {
                    PropertyCollection structProps = new PropertyCollection();
                    ClassInfo          tempInfo    = info;
                    while (tempInfo != null)
                    {
                        foreach ((string propName, PropertyInfo propInfo) in tempInfo.properties)
                        {
                            if (stripTransients && propInfo.Transient)
                            {
                                continue;
                            }
                            if (getDefaultProperty(propName, propInfo, stripTransients, isImmutable) is UProperty uProp)
                            {
                                structProps.Add(uProp);
                            }
                        }
                        if (!Structs.TryGetValue(tempInfo.baseClass, out tempInfo))
                        {
                            tempInfo = null;
                        }
                    }
                    structProps.Add(new NoneProperty());

                    string filepath = Path.Combine(ME1Directory.gamePath, "BioGame", info.pccPath);
                    if (File.Exists(info.pccPath))
                    {
                        filepath = info.pccPath; //Used for dynamic lookup
                    }
                    if (File.Exists(filepath))
                    {
                        IMEPackage         importPCC    = MEPackageHandler.OpenME1Package(filepath);
                        var                exportToRead = importPCC.getUExport(info.exportIndex);
                        byte[]             buff         = exportToRead.Data.Skip(0x30).ToArray();
                        PropertyCollection defaults     = PropertyCollection.ReadProps(exportToRead, new MemoryStream(buff), className);
                        foreach (var prop in defaults)
                        {
                            structProps.TryReplaceProp(prop);
                        }
                    }
                    return(structProps);
                }
                catch
                {
                    return(null);
                }
            }
            return(null);
        }
        public static List <ClassInfo> GetSequenceConditions(MEGame game)
        {
            List <ClassInfo> classes = UnrealObjectInfo.GetNonAbstractDerivedClassesOf(SequenceConditionName, game);

            if (game == MEGame.ME2)
            {
                return(classes.Where(info => EntryImporter.CanImport(info, MEGame.ME2)).ToList());
            }

            return(classes);
        }
        public static void TrashIncompatibleEntries(MEPackage pcc, MEGame oldGame, MEGame newGame)
        {
            var entries         = new EntryCollection(pcc);
            var oldClasses      = UnrealObjectInfo.GetClasses(oldGame);
            var newClasses      = UnrealObjectInfo.GetClasses(newGame);
            var classesToRemove = oldClasses.Keys.Except(newClasses.Keys).ToHashSet();

            foreach (IEntry entry in entries)
            {
                if (classesToRemove.Contains(entry.ClassName) || (entry.ClassName == "Class" && classesToRemove.Contains(entry.ObjectName)) ||
                    entry is ExportEntry exp && (pcc.getEntry(exp.idxArchtype)?.IsTrash() ?? false))
                {
                    TrashEntries(pcc, entries.FlattenTree(entry.UIndex));
                }
            }
        }
 public static List <ClassInfo> GetCommonObjects(MEGame game)
 {
     return(new List <string>
     {
         "Sequence",
         "SeqAct_Interp",
         "InterpData",
         "BioSeqAct_EndCurrentConvNode",
         "BioSeqEvt_ConvNode",
         "BioSeqVar_ObjectFindByTag",
         "SeqVar_Object",
         "SeqAct_ActivateRemoteEvent",
         "SeqEvent_SequenceActivated",
         "SeqAct_Delay",
         "SeqAct_Gate",
         "BioSeqAct_PMCheckState",
         "BioSeqAct_PMExecuteTransition",
         "SeqAct_FinishSequence"
     }.Select(className => UnrealObjectInfo.GetClassOrStructInfo(game, className)).NonNull().ToList());
 }
 public bool TryGetPropInfo(string name, Mod.MEGame game, out PropertyInfo propInfo) =>
 properties.TryGetValue(name, out propInfo) || (UnrealObjectInfo.GetClassOrStructInfo(game, baseClass)?.TryGetPropInfo(name, game, out propInfo) ?? false);
Exemple #6
0
        public static IEntry EnsureClassIsInFile(IMEPackage pcc, string className)
        {
            //check to see class is already in file
            foreach (ImportEntry import in pcc.Imports)
            {
                if (import.IsClass && import.ObjectName == className)
                {
                    return(import);
                }
            }
            foreach (ExportEntry export in pcc.Exports)
            {
                if (export.IsClass && export.ObjectName == className)
                {
                    return(export);
                }
            }

            ClassInfo info = UnrealObjectInfo.GetClassOrStructInfo(pcc.Game, className);

            //backup some package state so we can undo changes if something goes wrong
            int           exportCount    = pcc.ExportCount;
            int           importCount    = pcc.ImportCount;
            List <string> nameListBackup = pcc.Names.ToList();

            try
            {
                if (EntryImporter.IsSafeToImportFrom(info.pccPath, pcc.Game))
                {
                    string package = Path.GetFileNameWithoutExtension(info.pccPath);
                    return(pcc.getEntryOrAddImport($"{package}.{className}"));
                }

                //It's a class that's defined locally in every file that uses it.
                Stream loadStream = null;
                if (info.pccPath == UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName)
                {
                    loadStream = Utilities.GetCustomAppResourceStream(pcc.Game);
                    //string resourceFilePath = App.CustomResourceFilePath(pcc.Game);
                    //if (File.Exists(resourceFilePath))
                    //{
                    //    sourceFilePath = resourceFilePath;
                    //}
                }
                else
                {
                    string testPath = Path.Combine(MEDirectories.GetBioGamePath(pcc.Game), info.pccPath);
                    if (File.Exists(testPath))
                    {
                        loadStream = new MemoryStream(File.ReadAllBytes(testPath));
                    }
                    else if (pcc.Game == MEGame.ME1)
                    {
                        testPath = Path.Combine(ME1Directory.DefaultGamePath, info.pccPath);
                        if (File.Exists(testPath))
                        {
                            loadStream = new MemoryStream(File.ReadAllBytes(testPath));
                        }
                    }
                }

                if (loadStream == null)
                {
                    //can't find file to import from. This may occur if user does not have game or neccesary dlc installed
                    return(null);
                }

                using IMEPackage sourcePackage = MEPackageHandler.OpenMEPackageFromStream(loadStream);

                if (!sourcePackage.IsUExport(info.exportIndex))
                {
                    return(null); //not sure how this would happen
                }

                ExportEntry sourceClassExport = sourcePackage.GetUExport(info.exportIndex);

                if (sourceClassExport.ObjectName != className)
                {
                    return(null);
                }

                //Will make sure that, if the class is in a package, that package will exist in pcc
                IEntry parent = EntryImporter.GetOrAddCrossImportOrPackage(sourceClassExport.ParentFullPath, sourcePackage, pcc);

                var relinkResults = EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneAllDependencies, sourceClassExport, pcc, parent, true, out IEntry result);
                if (relinkResults?.Count > 0)
                {
                    ListDialog ld = new ListDialog(relinkResults, "Relink report", "The following items failed to relink.", null);
                    ld.Show();
                }
                return(result);
            }
            catch (Exception e)
            {
                //remove added entries
                var entriesToRemove = new List <IEntry>();
                for (int i = exportCount; i < pcc.Exports.Count; i++)
                {
                    entriesToRemove.Add(pcc.Exports[i]);
                }
                for (int i = importCount; i < pcc.Imports.Count; i++)
                {
                    entriesToRemove.Add(pcc.Imports[i]);
                }
                EntryPruner.TrashEntries(pcc, entriesToRemove);
                pcc.restoreNames(nameListBackup);
                return(null);
            }
        }
 public static PropertyCollection getDefaultStructValue(string className, bool stripTransients = true)
 {
     if (Structs.ContainsKey(className))
     {
         bool      immutable = UnrealObjectInfo.isImmutable(className, MEGame.ME2);
         ClassInfo info      = Structs[className];
         try
         {
             if (info.pccPath != "ME3Explorer_CustomNativeAdditions")
             {
                 string filepath = (Path.Combine(ME2Directory.gamePath, @"BioGame\" + info.pccPath));
                 if (File.Exists(info.pccPath))
                 {
                     filepath = info.pccPath; //Used for dynamic lookup
                 }
                 using (ME2Package importPCC = MEPackageHandler.OpenME2Package(filepath))
                 {
                     byte[] buff;
                     //Plane and CoverReference inherit from other structs, meaning they don't have default values (who knows why)
                     //thus, I have hardcoded what those default values should be
                     if (className == "Plane")
                     {
                         buff = PlaneDefault;
                     }
                     else if (className == "CoverReference")
                     {
                         buff = CoverReferenceDefault;
                     }
                     else
                     {
                         var exportToRead = importPCC.Exports[info.exportIndex];
                         buff = exportToRead.Data.Skip(0x30).ToArray();
                     }
                     PropertyCollection props = PropertyCollection.ReadProps(importPCC, new MemoryStream(buff), className);
                     if (stripTransients)
                     {
                         var toRemove = new List <UProperty>();
                         foreach (var prop in props)
                         {
                             //remove transient props
                             if (info.properties.TryGetValue(prop.Name, out PropertyInfo propInfo))
                             {
                                 if (propInfo.transient)
                                 {
                                     toRemove.Add(prop);
                                 }
                             }
                             //if (!info.properties.ContainsKey(prop.Name) && info.baseClass == "Class")
                             //{
                             //    toRemove.Add(prop);
                             //}
                         }
                         foreach (var prop in toRemove)
                         {
                             Debug.WriteLine($"ME2: Get Default Struct value ({className}) - removing transient prop: {prop.Name}");
                             props.Remove(prop);
                         }
                     }
                     return(props);
                 }
             }
         }
         catch
         {
             return(null);
         }
     }
     return(null);
 }
        public static UProperty getDefaultProperty(string propName, PropertyInfo propInfo, bool stripTransients = true, bool isImmutable = false)
        {
            switch (propInfo.Type)
            {
            case PropertyType.IntProperty:
                return(new IntProperty(0, propName));

            case PropertyType.FloatProperty:
                return(new FloatProperty(0f, propName));

            case PropertyType.DelegateProperty:
                return(new DelegateProperty(0, "None"));

            case PropertyType.ObjectProperty:
                return(new ObjectProperty(0, propName));

            case PropertyType.NameProperty:
                return(new NameProperty("None", propName));

            case PropertyType.BoolProperty:
                return(new BoolProperty(false, propName));

            case PropertyType.ByteProperty when propInfo.IsEnumProp():
                return(new EnumProperty(propInfo.Reference, MEGame.ME2, propName));

            case PropertyType.ByteProperty:
                return(new ByteProperty(0, propName));

            case PropertyType.StrProperty:
                return(new StrProperty("", propName));

            case PropertyType.StringRefProperty:
                return(new StringRefProperty(propName));

            case PropertyType.BioMask4Property:
                return(new BioMask4Property(0, propName));

            case PropertyType.ArrayProperty:
                switch (getArrayType(propInfo))
                {
                case ArrayType.Object:
                    return(new ArrayProperty <ObjectProperty>(propName));

                case ArrayType.Name:
                    return(new ArrayProperty <NameProperty>(propName));

                case ArrayType.Enum:
                    return(new ArrayProperty <EnumProperty>(propName));

                case ArrayType.Struct:
                    return(new ArrayProperty <StructProperty>(propName));

                case ArrayType.Bool:
                    return(new ArrayProperty <BoolProperty>(propName));

                case ArrayType.String:
                    return(new ArrayProperty <StrProperty>(propName));

                case ArrayType.Float:
                    return(new ArrayProperty <FloatProperty>(propName));

                case ArrayType.Int:
                    return(new ArrayProperty <IntProperty>(propName));

                case ArrayType.Byte:
                    return(new ImmutableByteArrayProperty(propName));

                default:
                    return(null);
                }

            case PropertyType.StructProperty:
                isImmutable = isImmutable || UnrealObjectInfo.IsImmutable(propInfo.Reference, MEGame.ME2);
                return(new StructProperty(propInfo.Reference, getDefaultStructValue(propInfo.Reference, stripTransients), propName, isImmutable));

            case PropertyType.None:
            case PropertyType.Unknown:
            default:
                return(null);
            }
        }
        public static PropertyCollection GetSequenceObjectDefaults(IMEPackage pcc, ClassInfo info)
        {
            MEGame             game     = pcc.Game;
            PropertyCollection defaults = new PropertyCollection();

            if (info.ClassName == "Sequence")
            {
                defaults.Add(new ArrayProperty <ObjectProperty>("SequenceObjects"));
            }
            else if (!info.IsA(SequenceVariableName, game))
            {
                ArrayProperty <StructProperty> varLinksProp   = null;
                ArrayProperty <StructProperty> outLinksProp   = null;
                ArrayProperty <StructProperty> eventLinksProp = null;
                ArrayProperty <StructProperty> inLinksProp    = null;
                Dictionary <string, ClassInfo> classes        = UnrealObjectInfo.GetClasses(game);
                try
                {
                    ClassInfo classInfo = info;
                    while (classInfo != null && (varLinksProp is null || outLinksProp is null || eventLinksProp is null || game == MEGame.ME1 && inLinksProp is null))
                    {
                        string filepath   = Path.Combine(MEDirectories.GetBioGamePath(game), classInfo.pccPath);
                        Stream loadStream = null;
                        if (File.Exists(classInfo.pccPath))
                        {
                            loadStream = new MemoryStream(File.ReadAllBytes(classInfo.pccPath));
                        }
                        else if (classInfo.pccPath == UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName)
                        {
                            loadStream = Utilities.GetCustomAppResourceStream(game);
                        }
                        else if (File.Exists(filepath))
                        {
                            loadStream = new MemoryStream(File.ReadAllBytes(filepath));
                        }
                        else if (game == MEGame.ME1)
                        {
                            filepath = Path.Combine(ME1Directory.DefaultGamePath, classInfo.pccPath); //for files from ME1 DLC
                            if (File.Exists(filepath))
                            {
                                loadStream = new MemoryStream(File.ReadAllBytes(filepath));
                            }
                        }
                        if (loadStream != null)
                        {
                            using IMEPackage importPCC = MEPackageHandler.OpenMEPackageFromStream(loadStream);
                            ExportEntry classExport   = importPCC.GetUExport(classInfo.exportIndex);
                            UClass      classBin      = ObjectBinary.From <UClass>(classExport);
                            ExportEntry classDefaults = importPCC.GetUExport(classBin.Defaults);

                            foreach (var prop in classDefaults.GetProperties())
                            {
                                if (varLinksProp == null && prop.Name == "VariableLinks" && prop is ArrayProperty <StructProperty> vlp)
                                {
                                    varLinksProp = vlp;
                                    //relink ExpectedType
                                    foreach (StructProperty varLink in varLinksProp)
                                    {
                                        if (varLink.GetProp <ObjectProperty>("ExpectedType") is ObjectProperty expectedTypeProp &&
                                            importPCC.TryGetEntry(expectedTypeProp.Value, out IEntry expectedVar) &&
                                            EntryImporterExtended.EnsureClassIsInFile(pcc, expectedVar.ObjectName) is IEntry portedExpectedVar)
                                        {
                                            expectedTypeProp.Value = portedExpectedVar.UIndex;
                                        }
                                    }
                                }
                                if (outLinksProp == null && prop.Name == "OutputLinks" && prop is ArrayProperty <StructProperty> olp)
                                {
                                    outLinksProp = olp;
                                }

                                if (eventLinksProp == null && prop.Name == "EventLinks" && prop is ArrayProperty <StructProperty> elp)
                                {
                                    eventLinksProp = elp;
                                    //relink ExpectedType
                                    foreach (StructProperty eventLink in eventLinksProp)
                                    {
                                        if (eventLink.GetProp <ObjectProperty>("ExpectedType") is ObjectProperty expectedTypeProp &&
                                            importPCC.TryGetEntry(expectedTypeProp.Value, out IEntry expectedVar) &&
                                            EntryImporterExtended.EnsureClassIsInFile(pcc, expectedVar.ObjectName) is IEntry portedExpectedVar)
                                        {
                                            expectedTypeProp.Value = portedExpectedVar.UIndex;
                                        }
                                    }
                                }

                                if (game == MEGame.ME1 && inLinksProp is null && prop.Name == "InputLinks" && prop is ArrayProperty <StructProperty> ilp)
                                {
                                    inLinksProp = ilp;
                                }
                            }
                        }
                        classes.TryGetValue(classInfo.baseClass, out classInfo);
                    }
                }
                catch
                {
                    // ignored
                }
                if (varLinksProp != null)
                {
                    defaults.Add(varLinksProp);
                }
                if (outLinksProp != null)
                {
                    defaults.Add(outLinksProp);
                }
                if (eventLinksProp != null)
                {
                    defaults.Add(eventLinksProp);
                }
                if (inLinksProp != null)
                {
                    defaults.Add(inLinksProp);
                }

                //remove links if empty
                if (defaults.GetProp <ArrayProperty <StructProperty> >("OutputLinks") is { } outLinks&& outLinks.IsEmpty())
                {
                    defaults.Remove(outLinks);
                }
                if (defaults.GetProp <ArrayProperty <StructProperty> >("VariableLinks") is { } varLinks&& varLinks.IsEmpty())
                {
                    defaults.Remove(varLinks);
                }
                if (defaults.GetProp <ArrayProperty <StructProperty> >("EventLinks") is { } eventLinks&& eventLinks.IsEmpty())
                {
                    defaults.Remove(eventLinks);
                }
                if (defaults.GetProp <ArrayProperty <StructProperty> >("InputLinks") is { } inputLinks&& inputLinks.IsEmpty())
                {
                    defaults.Remove(inputLinks);
                }
            }

            int objInstanceVersion = UnrealObjectInfo.getSequenceObjectInfo(game, info.ClassName)?.ObjInstanceVersion ?? 1;

            defaults.Add(new IntProperty(objInstanceVersion, "ObjInstanceVersion"));

            return(defaults);
        }
 public static PropertyCollection GetSequenceObjectDefaults(IMEPackage pcc, string className, MEGame game) => GetSequenceObjectDefaults(pcc, UnrealObjectInfo.GetClassOrStructInfo(game, className));
        public static List <ClassInfo> GetSequenceConditions(MEGame game)
        {
            List <ClassInfo> classes = UnrealObjectInfo.GetNonAbstractDerivedClassesOf(SequenceConditionName, game);

            return(classes);
        }
        public static PropertyCollection RemoveIncompatibleProperties(IMEPackage sourcePcc, PropertyCollection props, string typeName, MEGame newGame)
        {
            var infoProps = UnrealObjectInfo.GetAllProperties(newGame, typeName);

            var newProps = new PropertyCollection();

            foreach (UProperty prop in props)
            {
                if (infoProps.ContainsKey(prop.Name))
                {
                    switch (prop)
                    {
                    case ArrayProperty <DelegateProperty> adp:
                        //don't think these exist? if they do, delete them
                        break;

                    case ArrayProperty <EnumProperty> aep:
                        if (UnrealObjectInfo.GetEnumValues(newGame, aep.Reference) is List <NameReference> enumValues)
                        {
                            foreach (EnumProperty enumProperty in aep)
                            {
                                if (!enumValues.Contains(enumProperty.Value))
                                {
                                    enumProperty.Value = enumValues.First();     //hope that the first value is a reasonable default
                                }
                            }
                            newProps.Add(aep);
                        }
                        break;

                    case ArrayProperty <ObjectProperty> asp:
                        for (int i = asp.Count - 1; i >= 0; i--)
                        {
                            if (asp[i].Value == 0 || sourcePcc.getEntry(asp[i].Value) is IEntry entry && !entry.GetFullPath.StartsWith(UnrealPackageFile.TrashPackageName))
                            {
                                continue;
                            }
                            //delete if it references a trashed entry or if value is invalid
                            asp.RemoveAt(i);
                        }
                        newProps.Add(asp);
                        break;

                    case ArrayProperty <StructProperty> asp:
                        if (UnrealObjectInfo.GetStructs(newGame).ContainsKey(asp.Reference))
                        {
                            if (HasIncompatibleImmutabilities(asp.Reference, out bool newImmutability))
                            {
                                break;
                            }
                            foreach (StructProperty structProperty in asp)
                            {
                                structProperty.Properties  = RemoveIncompatibleProperties(sourcePcc, structProperty.Properties, structProperty.StructType, newGame);
                                structProperty.IsImmutable = newImmutability;
                            }
                            newProps.Add(asp);
                        }
                        break;

                    case DelegateProperty delegateProperty:
                        //script related, so just delete it.
                        break;

                    case EnumProperty enumProperty:
                        if (UnrealObjectInfo.GetEnumValues(newGame, enumProperty.EnumType) is List <NameReference> values)
                        {
                            if (!values.Contains(enumProperty.Value))
                            {
                                enumProperty.Value = values.First();     //hope that the first value is a reasonable default
                            }
                            newProps.Add(enumProperty);
                        }
                        break;

                    case ObjectProperty objectProperty:
                    {
                        if (objectProperty.Value == 0 || sourcePcc.getEntry(objectProperty.Value) is IEntry entry && !entry.GetFullPath.StartsWith(UnrealPackageFile.TrashPackageName))
                        {
                            newProps.Add(objectProperty);
                        }
                        break;
                    }

                    case StructProperty structProperty:
                        string structType = structProperty.StructType;
                        if (UnrealObjectInfo.GetStructs(newGame).ContainsKey(structType))
                        {
                            if (HasIncompatibleImmutabilities(structType, out bool newImmutability))
                            {
                                break;
                            }
                            structProperty.Properties  = RemoveIncompatibleProperties(sourcePcc, structProperty.Properties, structType, newGame);
                            structProperty.IsImmutable = newImmutability;
                            newProps.Add(structProperty);
                        }
                        break;

                    default:
                        newProps.Add(prop);
                        break;
                    }
                }
            }

            return(newProps);

            bool HasIncompatibleImmutabilities(string structType, out bool newImmutability)
            {
                bool sourceIsImmutable = UnrealObjectInfo.IsImmutable(structType, sourcePcc.Game);

                newImmutability = UnrealObjectInfo.IsImmutable(structType, newGame);

                if (sourceIsImmutable && newImmutability && !UnrealObjectInfo.GetClassOrStructInfo(sourcePcc.Game, structType).properties
                    .SequenceEqual(UnrealObjectInfo.GetClassOrStructInfo(newGame, structType).properties))
                {
                    //both immutable, but have different properties
                    return(true);
                }

                if (!sourceIsImmutable && newImmutability)
                {
                    //can't easily guarantee it will have have all neccesary properties
                    return(true);
                }

                return(false);
            }
        }
        public static PropertyCollection getDefaultStructValue(string className, bool stripTransients)
        {
            bool isImmutable = UnrealObjectInfo.IsImmutable(className, MEGame.ME2);

            if (Structs.ContainsKey(className))
            {
                ClassInfo info = Structs[className];
                try
                {
                    PropertyCollection structProps = new PropertyCollection();
                    ClassInfo          tempInfo    = info;
                    while (tempInfo != null)
                    {
                        foreach ((string propName, PropertyInfo propInfo) in tempInfo.properties)
                        {
                            if (stripTransients && propInfo.Transient)
                            {
                                continue;
                            }
                            if (getDefaultProperty(propName, propInfo, stripTransients, isImmutable) is Property uProp)
                            {
                                structProps.Add(uProp);
                            }
                        }
                        if (!Structs.TryGetValue(tempInfo.baseClass, out tempInfo))
                        {
                            tempInfo = null;
                        }
                    }
                    structProps.Add(new NoneProperty());

                    string filepath = null;
                    if (ME2Directory.BioGamePath != null)
                    {
                        filepath = Path.Combine(ME2Directory.BioGamePath, info.pccPath);
                    }

                    Stream loadStream = null;
                    if (File.Exists(info.pccPath))
                    {
                        filepath   = info.pccPath;
                        loadStream = new MemoryStream(File.ReadAllBytes(info.pccPath));
                    }
                    else if (info.pccPath == UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName)
                    {
                        filepath   = "GAMERESOURCES_ME2";
                        loadStream = Utilities.LoadFileFromCompressedResource("GameResources.zip", CoreLib.CustomResourceFileName(MEGame.ME2));
                    }
                    else if (filepath != null && File.Exists(filepath))
                    {
                        loadStream = new MemoryStream(File.ReadAllBytes(filepath));
                    }
#if AZURE
                    else if (MiniGameFilesPath != null && File.Exists(Path.Combine(MiniGameFilesPath, info.pccPath)))
                    {
                        // Load from test minigame folder. This is only really useful on azure where we don't have access to
                        // games
                        filepath   = Path.Combine(MiniGameFilesPath, info.pccPath);
                        loadStream = new MemoryStream(File.ReadAllBytes(filepath));
                    }
#endif

                    if (loadStream != null)
                    {
                        using (IMEPackage importPCC = MEPackageHandler.OpenMEPackageFromStream(loadStream, filepath, useSharedPackageCache: true))
                        {
                            var                exportToRead = importPCC.GetUExport(info.exportIndex);
                            byte[]             buff         = exportToRead.Data.Skip(0x30).ToArray();
                            PropertyCollection defaults     = PropertyCollection.ReadProps(exportToRead, new MemoryStream(buff), className);
                            foreach (var prop in defaults)
                            {
                                structProps.TryReplaceProp(prop);
                            }
                        }
                    }
                    return(structProps);
                }
                catch
                {
                    return(null);
                }
            }
            return(null);
        }