コード例 #1
0
ファイル: IoPackage.cs プロジェクト: Pro-Swapper/ProSwapper
        public IoPackage(
            FArchive uasset, IoGlobalData globalData,
            Lazy <FArchive?>?ubulk = null, Lazy <FArchive?>?uptnl = null,
            IFileProvider?provider = null, TypeMappings?mappings  = null) : base(uasset.Name.SubstringBeforeLast('.'), provider, mappings)
        {
            GlobalData = globalData;
            var uassetAr = new FAssetArchive(uasset, this);

            FExportBundleHeader[] exportBundleHeaders;
            FExportBundleEntry[]  exportBundleEntries;
            FPackageId[]          importedPackageIds;
            int allExportDataOffset;

            if (uassetAr.Game >= EGame.GAME_UE5_0)
            {
                // Summary
                var summary = uassetAr.Read <FPackageSummary5>();
                Summary = new FPackageFileSummary
                {
                    PackageFlags    = summary.PackageFlags,
                    TotalHeaderSize = summary.GraphDataOffset + (int)summary.HeaderSize,
                    ExportCount     = (summary.ExportBundleEntriesOffset - summary.ExportMapOffset) / Unsafe.SizeOf <FExportMapEntry>(),
                    ImportCount     = (summary.ExportMapOffset - summary.ImportMapOffset) / FPackageObjectIndex.Size
                };

                // Name map
                NameMap           = FNameEntrySerialized.LoadNameBatch(uassetAr);
                Summary.NameCount = NameMap.Length;
                Name = CreateFNameFromMappedName(summary.Name).Text;

                // Import map
                uassetAr.Position = summary.ImportMapOffset;
                ImportMap         = uasset.ReadArray <FPackageObjectIndex>(Summary.ImportCount);

                // Export map
                uassetAr.Position = summary.ExportMapOffset;
                ExportMap         = uasset.ReadArray <FExportMapEntry>(Summary.ExportCount);
                ExportsLazy       = new Lazy <UObject> [Summary.ExportCount];

                // Export bundle entries
                uassetAr.Position   = summary.ExportBundleEntriesOffset;
                exportBundleEntries = uassetAr.ReadArray <FExportBundleEntry>(Summary.ExportCount * 2);

                // Export bundle headers
                uassetAr.Position = summary.GraphDataOffset;
                var exportBundleHeadersCount = 1; // TODO just a placeholder until loading of package store entries are implemented
                exportBundleHeaders = uassetAr.ReadArray <FExportBundleHeader>(exportBundleHeadersCount);
                // We don't read the graph data

                importedPackageIds = Array.Empty <FPackageId>(); // TODO imported packages are now only stored in the package store entry, no longer in the graph data too

                allExportDataOffset = (int)summary.HeaderSize;
            }
            else
            {
                // Summary
                var summary = uassetAr.Read <FPackageSummary>();
                Summary = new FPackageFileSummary
                {
                    PackageFlags    = summary.PackageFlags,
                    TotalHeaderSize = summary.GraphDataOffset + summary.GraphDataSize,
                    NameCount       = summary.NameMapHashesSize / sizeof(ulong) - 1,
                    ExportCount     = (summary.ExportBundlesOffset - summary.ExportMapOffset) / Unsafe.SizeOf <FExportMapEntry>(),
                    ImportCount     = (summary.ExportMapOffset - summary.ImportMapOffset) / FPackageObjectIndex.Size
                };

                // Name map
                uassetAr.Position = summary.NameMapNamesOffset;
                NameMap           = FNameEntrySerialized.LoadNameBatch(uassetAr, Summary.NameCount);
                Name = CreateFNameFromMappedName(summary.Name).Text;

                // Import map
                uassetAr.Position = summary.ImportMapOffset;
                ImportMap         = uasset.ReadArray <FPackageObjectIndex>(Summary.ImportCount);

                // Export map
                uassetAr.Position = summary.ExportMapOffset;
                ExportMap         = uasset.ReadArray <FExportMapEntry>(Summary.ExportCount);
                ExportsLazy       = new Lazy <UObject> [Summary.ExportCount];

                // Export bundles
                uassetAr.Position = summary.ExportBundlesOffset;
                LoadExportBundles(uassetAr, summary.GraphDataOffset - summary.ExportBundlesOffset, out exportBundleHeaders, out exportBundleEntries);

                // Graph data
                uassetAr.Position  = summary.GraphDataOffset;
                importedPackageIds = LoadGraphData(uassetAr);

                allExportDataOffset = summary.GraphDataOffset + summary.GraphDataSize;
            }

            // Preload dependencies
            ImportedPackages = new Lazy <IoPackage?[]>(provider != null ? () =>
            {
                var packages = new IoPackage?[importedPackageIds.Length];
                for (int i = 0; i < importedPackageIds.Length; i++)
                {
                    provider.TryLoadPackage(importedPackageIds[i], out packages[i]);
                }
                return(packages);
            } : Array.Empty <IoPackage?>);

            // Attach ubulk and uptnl
            if (ubulk != null)
            {
                uassetAr.AddPayload(PayloadType.UBULK, Summary.BulkDataStartOffset, ubulk);
            }
            if (uptnl != null)
            {
                uassetAr.AddPayload(PayloadType.UPTNL, Summary.BulkDataStartOffset, uptnl);
            }

            // Populate lazy exports
            var currentExportDataOffset = allExportDataOffset;

            foreach (var exportBundle in exportBundleHeaders)
            {
                for (var i = 0u; i < exportBundle.EntryCount; i++)
                {
                    var entry = exportBundleEntries[exportBundle.FirstEntryIndex + i];
                    if (entry.CommandType == EExportCommandType.ExportCommandType_Serialize)
                    {
                        var localExportIndex      = entry.LocalExportIndex;
                        var export                = ExportMap[localExportIndex];
                        var localExportDataOffset = currentExportDataOffset;
                        ExportsLazy[localExportIndex] = new Lazy <UObject>(() =>
                        {
                            // Create
                            var obj      = ConstructObject(ResolveObjectIndex(export.ClassIndex)?.Object?.Value as UStruct);
                            obj.Name     = CreateFNameFromMappedName(export.ObjectName).Text;
                            obj.Outer    = (ResolveObjectIndex(export.OuterIndex) as ResolvedExportObject)?.ExportObject.Value ?? this;
                            obj.Super    = ResolveObjectIndex(export.SuperIndex) as ResolvedExportObject;
                            obj.Template = ResolveObjectIndex(export.TemplateIndex) as ResolvedExportObject;
                            obj.Flags   |= (EObjectFlags)export.ObjectFlags; // We give loaded objects the RF_WasLoaded flag in ConstructObject, so don't remove it again in here

                            // Serialize
                            uassetAr.AbsoluteOffset = (int)export.CookedSerialOffset - localExportDataOffset;
                            uassetAr.Seek(localExportDataOffset, SeekOrigin.Begin);
                            DeserializeObject(obj, uassetAr, (long)export.CookedSerialSize);
                            // TODO right place ???
                            obj.Flags |= EObjectFlags.RF_LoadCompleted;
                            obj.PostLoad();
                            return(obj);
                        });
                        currentExportDataOffset += (int)export.CookedSerialSize;
                    }
                }
            }

            Summary.BulkDataStartOffset = currentExportDataOffset;
        }
コード例 #2
0
ファイル: IoPackage.cs プロジェクト: razfriman/CUE4Parse
        public IoPackage(
            FArchive uasset, IoGlobalData globalData,
            Lazy <FArchive?>?ubulk = null, Lazy <FArchive?>?uptnl = null,
            IFileProvider?provider = null, TypeMappings?mappings  = null) : base(uasset.Name.SubstringBeforeLast(".uasset"), provider, mappings)
        {
            if (provider == null)
            {
                throw new ParserException("Cannot load I/O store package without a file provider. This is needed to link the package imports.");
            }

            GlobalData = globalData;
            var uassetAr = new FAssetArchive(uasset, this);

            // Summary
            IoSummary = uassetAr.Read <FPackageSummary>();
            Summary   = new FPackageFileSummary
            {
                PackageFlags    = (PackageFlags)IoSummary.PackageFlags,
                TotalHeaderSize = IoSummary.GraphDataOffset + IoSummary.GraphDataSize,
                NameCount       = IoSummary.NameMapHashesSize / sizeof(ulong) - 1,
                ExportCount     = (IoSummary.ExportBundlesOffset - IoSummary.ExportMapOffset) / Unsafe.SizeOf <FExportMapEntry>(),
                ImportCount     = (IoSummary.ExportMapOffset - IoSummary.ImportMapOffset) / FPackageObjectIndex.Size
            };

            // Name map
            uassetAr.Position = IoSummary.NameMapNamesOffset;
            NameMap           = FNameEntrySerialized.LoadNameBatch(uassetAr, Summary.NameCount);
            Name = CreateFNameFromMappedName(IoSummary.Name).Text;

            // Import map
            uassetAr.Position = IoSummary.ImportMapOffset;
            ImportMap         = uasset.ReadArray <FPackageObjectIndex>(Summary.ImportCount);

            // Export map
            uassetAr.Position = IoSummary.ExportMapOffset;
            ExportMap         = uasset.ReadArray <FExportMapEntry>(Summary.ExportCount);
            ExportsLazy       = new Lazy <UObject> [Summary.ExportCount];

            // Export bundles
            uassetAr.Position = IoSummary.ExportBundlesOffset;
            LoadExportBundles(uassetAr, out var exportBundleHeaders, out var exportBundleEntries);

            // Graph data
            uassetAr.Position = IoSummary.GraphDataOffset;
            var importedPackageIds = LoadGraphData(uassetAr);

            // Preload dependencies
            ImportedPackages = new Lazy <IoPackage?[]>(() =>
            {
                var packages = new IoPackage?[importedPackageIds.Length];
                for (int i = 0; i < importedPackageIds.Length; i++)
                {
                    provider.TryLoadPackage(importedPackageIds[i], out packages[i]);
                }
                return(packages);
            });

            // Attach ubulk and uptnl
            if (ubulk != null)
            {
                uassetAr.AddPayload(PayloadType.UBULK, Summary.BulkDataStartOffset, ubulk);
            }
            if (uptnl != null)
            {
                uassetAr.AddPayload(PayloadType.UPTNL, Summary.BulkDataStartOffset, uptnl);
            }

            // Populate lazy exports
            var allExportDataOffset     = IoSummary.GraphDataOffset + IoSummary.GraphDataSize;
            var currentExportDataOffset = allExportDataOffset;

            foreach (var exportBundle in exportBundleHeaders)
            {
                for (var i = 0u; i < exportBundle.EntryCount; i++)
                {
                    var entry = exportBundleEntries[exportBundle.FirstEntryIndex + i];
                    if (entry.CommandType == EExportCommandType.ExportCommandType_Serialize)
                    {
                        var localExportIndex      = entry.LocalExportIndex;
                        var export                = ExportMap[localExportIndex];
                        var localExportDataOffset = currentExportDataOffset;
                        ExportsLazy[localExportIndex] = new Lazy <UObject>(() =>
                        {
                            // Create
                            var objectName = CreateFNameFromMappedName(export.ObjectName);
                            var obj        = ConstructObject(ResolveObjectIndex(export.ClassIndex)?.Object?.Value as UStruct);
                            obj.Name       = objectName.Text;
                            obj.Outer      = (ResolveObjectIndex(export.OuterIndex) as ResolvedExportObject)?.ExportObject.Value ?? this;
                            obj.Template   = ResolveObjectIndex(export.TemplateIndex) as ResolvedExportObject;
                            obj.Flags      = (int)export.ObjectFlags;
                            var exportType = obj.ExportType;

                            // Serialize
                            uassetAr.AbsoluteOffset = (int)export.CookedSerialOffset - localExportDataOffset;
                            uassetAr.Seek(localExportDataOffset, SeekOrigin.Begin);
                            var validPos = uassetAr.Position + (long)export.CookedSerialSize;
                            try
                            {
                                obj.Deserialize(uassetAr, validPos);
#if DEBUG
                                if (validPos != uassetAr.Position)
                                {
                                    Log.Warning("Did not read {0} correctly, {1} bytes remaining", exportType, validPos - uassetAr.Position);
                                }
                                else
                                {
                                    Log.Debug("Successfully read {0} at {1} with size {2}", exportType, localExportDataOffset, export.CookedSerialSize);
                                }
#endif
                                // TODO right place ???
                                obj.PostLoad();
                            }
                            catch (Exception e)
                            {
                                Log.Error(e, "Could not read {0} correctly", exportType);
                            }
                            return(obj);
                        });
                        currentExportDataOffset += (int)export.CookedSerialSize;
                    }
                }
            }

            Summary.BulkDataStartOffset = currentExportDataOffset;
        }
コード例 #3
0
ファイル: Package.cs プロジェクト: Pro-Swapper/ProSwapper
        public Package(FArchive uasset, FArchive?uexp, Lazy <FArchive?>?ubulk = null, Lazy <FArchive?>?uptnl = null, IFileProvider?provider = null, TypeMappings?mappings = null, bool useLazySerialization = true)
            : base(uasset.Name.SubstringBeforeLast(".uasset"), provider, mappings)
        {
            // We clone the version container because it can be modified with package specific versions when reading the summary
            uasset.Versions = (VersionContainer)uasset.Versions.Clone();
            var uassetAr = new FAssetArchive(uasset, this);

            Summary = new FPackageFileSummary(uassetAr);

            uassetAr.SeekAbsolute(Summary.NameOffset, SeekOrigin.Begin);
            NameMap = new FNameEntrySerialized[Summary.NameCount];
            uassetAr.ReadArray(NameMap, () => new FNameEntrySerialized(uassetAr));

            uassetAr.SeekAbsolute(Summary.ImportOffset, SeekOrigin.Begin);
            ImportMap = new FObjectImport[Summary.ImportCount];
            uassetAr.ReadArray(ImportMap, () => new FObjectImport(uassetAr));

            uassetAr.SeekAbsolute(Summary.ExportOffset, SeekOrigin.Begin);
            ExportMap = new FObjectExport[Summary.ExportCount]; // we need this to get its final size in some case
            uassetAr.ReadArray(ExportMap, () => new FObjectExport(uassetAr));

            FAssetArchive uexpAr = uexp != null ? new FAssetArchive(uexp, this, (int)uassetAr.Length) : uassetAr;  // allows embedded uexp data

            if (ubulk != null)
            {
                //var offset = (int) (Summary.TotalHeaderSize + ExportMap.Sum(export => export.SerialSize));
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UBULK, offset, ubulk);
            }

            if (uptnl != null)
            {
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UPTNL, offset, uptnl);
            }

            if (useLazySerialization)
            {
                foreach (var export in ExportMap)
                {
                    export.ExportObject = new Lazy <UObject>(() =>
                    {
                        // Create
                        var obj      = ConstructObject(ResolvePackageIndex(export.ClassIndex)?.Object?.Value as UStruct);
                        obj.Name     = export.ObjectName.Text;
                        obj.Outer    = (ResolvePackageIndex(export.OuterIndex) as ResolvedExportObject)?.Object.Value ?? this;
                        obj.Super    = ResolvePackageIndex(export.SuperIndex) as ResolvedExportObject;
                        obj.Template = ResolvePackageIndex(export.TemplateIndex) as ResolvedExportObject;
                        obj.Flags   |= (EObjectFlags)export.ObjectFlags; // We give loaded objects the RF_WasLoaded flag in ConstructObject, so don't remove it again in here

                        // Serialize
                        uexpAr.SeekAbsolute(export.SerialOffset, SeekOrigin.Begin);
                        DeserializeObject(obj, uexpAr, export.SerialSize);
                        // TODO right place ???
                        obj.Flags |= EObjectFlags.RF_LoadCompleted;
                        obj.PostLoad();
                        return(obj);
                    });
                }
            }
            else
            {
                var newObjNames = new List <string>();
                foreach (var export in ExportMap)
                {
                    if (export.ExportObject == null)
                    {
                        var obj = ConstructObject(ResolvePackageIndex(export.ClassIndex)?.Object?.Value as UStruct);
                        obj.Name     = export.ObjectName.Text;
                        obj.Super    = ResolvePackageIndex(export.SuperIndex) as ResolvedExportObject;
                        obj.Template = ResolvePackageIndex(export.TemplateIndex) as ResolvedExportObject;
                        obj.Flags   |= (EObjectFlags)export.ObjectFlags; // We give loaded objects the RF_WasLoaded flag in ConstructObject, so don't remove it again in here

                        export.ExportObject = new Lazy <UObject>(obj);
                        newObjNames.Add(export.ObjectName.Text);
                    }
                }

                foreach (var export in ExportMap)
                {
                    if (newObjNames.Contains(export.ObjectName.Text))
                    {
                        var obj = export.ExportObject.Value;

                        uexpAr.SeekAbsolute(export.SerialOffset, SeekOrigin.Begin);
                        DeserializeObject(obj, uexpAr, export.SerialSize);
                    }
                }

                foreach (var export in ExportMap)
                {
                    if (newObjNames.Contains(export.ObjectName.Text))
                    {
                        var obj = export.ExportObject.Value;
                        obj.Outer = (ResolvePackageIndex(export.OuterIndex) as ResolvedExportObject)?.Object.Value ?? this;
                    }
                }

                foreach (var export in ExportMap)
                {
                    if (newObjNames.Contains(export.ObjectName.Text))
                    {
                        var obj = export.ExportObject.Value;

                        obj.Flags |= EObjectFlags.RF_LoadCompleted;
                        obj.PostLoad();
                    }
                }
            }
        }
コード例 #4
0
        public IoPackage(
            FArchive uasset, IoGlobalData globalData, FIoContainerHeader?containerHeader = null,
            Lazy <FArchive?>?ubulk = null, Lazy <FArchive?>?uptnl = null,
            IFileProvider?provider = null, TypeMappings?mappings  = null) : base(uasset.Name.SubstringBeforeLast('.'), provider, mappings)
        {
            GlobalData = globalData;
            var uassetAr = new FAssetArchive(uasset, this);

            FExportBundleHeader[] exportBundleHeaders;
            FExportBundleEntry[]  exportBundleEntries;
            FPackageId[]          importedPackageIds;
            int allExportDataOffset;

            if (uassetAr.Game >= EGame.GAME_UE5_0)
            {
                // Summary
                var summary = uassetAr.Read <FZenPackageSummary>();
                Summary = new FPackageFileSummary
                {
                    PackageFlags    = summary.PackageFlags,
                    TotalHeaderSize = summary.GraphDataOffset + (int)summary.HeaderSize,
                    ExportCount     = (summary.ExportBundleEntriesOffset - summary.ExportMapOffset) / FExportMapEntry.Size,
                    ImportCount     = (summary.ExportMapOffset - summary.ImportMapOffset) / FPackageObjectIndex.Size
                };

                // Versioning info
                if (summary.bHasVersioningInfo != 0)
                {
                    var versioningInfo = new FZenPackageVersioningInfo(uassetAr);
                    Summary.FileVersionUE          = versioningInfo.PackageVersion;
                    Summary.FileVersionLicenseeUE  = (EUnrealEngineObjectLicenseeUEVersion)versioningInfo.LicenseeVersion;
                    Summary.CustomVersionContainer = versioningInfo.CustomVersions;
                    if (!uassetAr.Versions.bExplicitVer)
                    {
                        uassetAr.Versions.Ver            = versioningInfo.PackageVersion;
                        uassetAr.Versions.CustomVersions = versioningInfo.CustomVersions.ToList();
                    }
                }
                else
                {
                    Summary.bUnversioned = true;
                }

                // Name map
                NameMap           = FNameEntrySerialized.LoadNameBatch(uassetAr);
                Summary.NameCount = NameMap.Length;
                Name = CreateFNameFromMappedName(summary.Name).Text;

                // Find store entry by package name
                FFilePackageStoreEntry?storeEntry = null;
                if (containerHeader != null)
                {
                    var storeEntryIdx = Array.IndexOf(containerHeader.PackageIds, FPackageId.FromName(Name));
                    if (storeEntryIdx != -1)
                    {
                        storeEntry = containerHeader.StoreEntries[storeEntryIdx];
                    }
                    else
                    {
                        Log.Warning("Couldn't find store entry for package {0}, its data will not be fully read", Name);
                    }
                }

                // Imported public export hashes
                uassetAr.Position          = summary.ImportedPublicExportHashesOffset;
                ImportedPublicExportHashes = uassetAr.ReadArray <ulong>((summary.ImportMapOffset - summary.ImportedPublicExportHashesOffset) / sizeof(ulong));

                // Import map
                uassetAr.Position = summary.ImportMapOffset;
                ImportMap         = uasset.ReadArray <FPackageObjectIndex>(Summary.ImportCount);

                // Export map
                uassetAr.Position = summary.ExportMapOffset;
                ExportMap         = uasset.ReadArray(Summary.ExportCount, () => new FExportMapEntry(uassetAr));
                ExportsLazy       = new Lazy <UObject> [Summary.ExportCount];

                // Export bundle entries
                uassetAr.Position   = summary.ExportBundleEntriesOffset;
                exportBundleEntries = uassetAr.ReadArray <FExportBundleEntry>(Summary.ExportCount * 2);

                // Export bundle headers
                uassetAr.Position = summary.GraphDataOffset;
                var exportBundleHeadersCount = storeEntry?.ExportBundleCount ?? 1;
                exportBundleHeaders = uassetAr.ReadArray <FExportBundleHeader>(exportBundleHeadersCount);
                // We don't read the graph data

                importedPackageIds = storeEntry?.ImportedPackages ?? Array.Empty <FPackageId>();

                allExportDataOffset = (int)summary.HeaderSize;
            }
            else
            {
                // Summary
                var summary = uassetAr.Read <FPackageSummary>();
                Summary = new FPackageFileSummary
                {
                    PackageFlags    = summary.PackageFlags,
                    TotalHeaderSize = summary.GraphDataOffset + summary.GraphDataSize,
                    NameCount       = summary.NameMapHashesSize / sizeof(ulong) - 1,
                    ExportCount     = (summary.ExportBundlesOffset - summary.ExportMapOffset) / FExportMapEntry.Size,
                    ImportCount     = (summary.ExportMapOffset - summary.ImportMapOffset) / FPackageObjectIndex.Size,
                    bUnversioned    = true
                };

                // Name map
                uassetAr.Position = summary.NameMapNamesOffset;
                NameMap           = FNameEntrySerialized.LoadNameBatch(uassetAr, Summary.NameCount);
                Name = CreateFNameFromMappedName(summary.Name).Text;

                // Import map
                uassetAr.Position = summary.ImportMapOffset;
                ImportMap         = uasset.ReadArray <FPackageObjectIndex>(Summary.ImportCount);

                // Export map
                uassetAr.Position = summary.ExportMapOffset;
                ExportMap         = uasset.ReadArray(Summary.ExportCount, () => new FExportMapEntry(uassetAr));
                ExportsLazy       = new Lazy <UObject> [Summary.ExportCount];

                // Export bundles
                uassetAr.Position = summary.ExportBundlesOffset;
                LoadExportBundles(uassetAr, summary.GraphDataOffset - summary.ExportBundlesOffset, out exportBundleHeaders, out exportBundleEntries);

                // Graph data
                uassetAr.Position  = summary.GraphDataOffset;
                importedPackageIds = LoadGraphData(uassetAr);

                allExportDataOffset = summary.GraphDataOffset + summary.GraphDataSize;
            }

            // Preload dependencies
            ImportedPackages = new Lazy <IoPackage?[]>(provider != null ? () =>
            {
                var packages = new IoPackage?[importedPackageIds.Length];
                for (int i = 0; i < importedPackageIds.Length; i++)
                {
                    provider.TryLoadPackage(importedPackageIds[i], out packages[i]);
                }
                return(packages);
            } : Array.Empty <IoPackage?>);

            // Attach ubulk and uptnl
            if (ubulk != null)
            {
                uassetAr.AddPayload(PayloadType.UBULK, Summary.BulkDataStartOffset, ubulk);
            }
            if (uptnl != null)
            {
                uassetAr.AddPayload(PayloadType.UPTNL, Summary.BulkDataStartOffset, uptnl);
            }

            // Populate lazy exports
            var currentExportDataOffset = allExportDataOffset;

            foreach (var exportBundle in exportBundleHeaders)
            {
                for (var i = 0u; i < exportBundle.EntryCount; i++)
                {
                    var entry = exportBundleEntries[exportBundle.FirstEntryIndex + i];
                    if (entry.CommandType == EExportCommandType.ExportCommandType_Serialize)
                    {
                        var localExportIndex      = entry.LocalExportIndex;
                        var export                = ExportMap[localExportIndex];
                        var localExportDataOffset = currentExportDataOffset;
                        ExportsLazy[localExportIndex] = new Lazy <UObject>(() =>
                        {
                            // Create
                            var obj      = ConstructObject(ResolveObjectIndex(export.ClassIndex)?.Object?.Value as UStruct);
                            obj.Name     = CreateFNameFromMappedName(export.ObjectName).Text;
                            obj.Outer    = (ResolveObjectIndex(export.OuterIndex) as ResolvedExportObject)?.ExportObject.Value ?? this;
                            obj.Super    = ResolveObjectIndex(export.SuperIndex) as ResolvedExportObject;
                            obj.Template = ResolveObjectIndex(export.TemplateIndex) as ResolvedExportObject;
                            obj.Flags   |= export.ObjectFlags; // We give loaded objects the RF_WasLoaded flag in ConstructObject, so don't remove it again in here

                            // Serialize
                            var Ar            = (FAssetArchive)uassetAr.Clone();
                            Ar.AbsoluteOffset = (int)export.CookedSerialOffset - localExportDataOffset;
                            Ar.Position       = localExportDataOffset;
                            DeserializeObject(obj, Ar, (long)export.CookedSerialSize);
                            // TODO right place ???
                            obj.Flags |= EObjectFlags.RF_LoadCompleted;
                            obj.PostLoad();
                            return(obj);
                        });
                        currentExportDataOffset += (int)export.CookedSerialSize;
                    }
                }
            }

            Summary.BulkDataStartOffset = currentExportDataOffset;

            IsFullyLoaded = true;
        }
コード例 #5
0
ファイル: Package.cs プロジェクト: razfriman/CUE4Parse
        public Package(FArchive uasset, FArchive uexp, Lazy <FArchive?>?ubulk = null, Lazy <FArchive?>?uptnl = null, IFileProvider?provider = null, TypeMappings?mappings = null)
            : base(uasset.Name.SubstringBeforeLast(".uasset"), provider, mappings)
        {
            var uassetAr = new FAssetArchive(uasset, this);

            Summary = new FPackageFileSummary(uassetAr);
            if (Summary.Tag != PackageMagic)
            {
                throw new ParserException(uassetAr, $"Invalid uasset magic: {Summary.Tag} != {PackageMagic}");
            }

            uassetAr.Seek(Summary.NameOffset, SeekOrigin.Begin);
            NameMap = new FNameEntrySerialized[Summary.NameCount];
            uassetAr.ReadArray(NameMap, () => new FNameEntrySerialized(uassetAr));

            uassetAr.Seek(Summary.ImportOffset, SeekOrigin.Begin);
            ImportMap = new FObjectImport[Summary.ImportCount];
            uassetAr.ReadArray(ImportMap, () => new FObjectImport(uassetAr));

            uassetAr.Seek(Summary.ExportOffset, SeekOrigin.Begin);
            ExportMap = new FObjectExport[Summary.ExportCount]; // we need this to get its final size in some case
            uassetAr.ReadArray(ExportMap, () => new FObjectExport(uassetAr));

            var uexpAr = new FAssetArchive(uexp, this, Summary.TotalHeaderSize);

            if (ubulk != null)
            {
                //var offset = (int) (Summary.TotalHeaderSize + ExportMap.Sum(export => export.SerialSize));
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UBULK, offset, ubulk);
            }

            if (uptnl != null)
            {
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UPTNL, offset, uptnl);
            }

            foreach (var it in ExportMap)
            {
                if (ResolvePackageIndex(it.ClassIndex)?.Object?.Value is not UStruct uStruct)
                {
                    continue;
                }
                var export = ConstructObject(uStruct);
                export.Name     = it.ObjectName.Text;
                export.Outer    = (ResolvePackageIndex(it.OuterIndex) as ResolvedExportObject)?.Object?.Value ?? this;
                export.Template = ResolvePackageIndex(it.TemplateIndex) as ResolvedExportObject;
                export.Flags    = (int)it.ObjectFlags;
                it.ExportType   = export.GetType();
                it.ExportObject = new Lazy <UObject>(() =>
                {
                    uexpAr.SeekAbsolute(it.RealSerialOffset, SeekOrigin.Begin);
                    var validPos = uexpAr.Position + it.SerialSize;
                    try
                    {
                        export.Deserialize(uexpAr, validPos);
#if DEBUG
                        if (validPos != uexpAr.Position)
                        {
                            Log.Warning("Did not read {0} correctly, {1} bytes remaining", export.ExportType, validPos - uexpAr.Position);
                        }
                        else
                        {
                            Log.Debug("Successfully read {0} at {1} with size {2}", export.ExportType, it.RealSerialOffset, it.SerialSize);
                        }
#endif

                        // TODO right place ???
                        export.PostLoad();
                    }
                    catch (Exception e)
                    {
                        Log.Error(e, "Could not read {0} correctly", export.ExportType);
                    }

                    return(export);
                });
            }
        }