FObjectImport[] SerializeImportMap() { if (PackageFileSummary.ImportCount > 0) { Loader.BaseStream.Position = PackageFileSummary.ImportOffset; var OutImportMap = new FObjectImport[PackageFileSummary.ImportCount]; for (int ImportMapIdx = 0; ImportMapIdx < PackageFileSummary.ImportCount; ++ImportMapIdx) { OutImportMap[ImportMapIdx] = new FObjectImport(this); } return(OutImportMap); } return(Array.Empty <FObjectImport>()); }
public UAsset(byte[] data, int version) : base(data) { Version = version; ReadSummary(); Seek(Summary.NameOffset); foreach (var i in Enumerable.Range(0, Summary.NameCount)) { var entry = new FNameEntrySerialized(); entry.Serialize(this); NameMap.Add(entry.Name); } Seek(Summary.GatherableTextDataOffset); foreach (var i in Enumerable.Range(0, Summary.GatherableTextDataCount)) { Debugger.Break(); // check whether it reads stuff properly var gatherable = new FGatherableTextData(); gatherable.Serialize(this); GatherableTextDataMap.Add(gatherable); } Seek(Summary.ImportOffset); foreach (var i in Enumerable.Range(0, Summary.ImportCount)) { var imp = new FObjectImport(); imp.Serialize(this); ImportMap.Add(imp); } Seek(Summary.ExportOffset); foreach (var i in Enumerable.Range(0, Summary.ExportCount)) { var exp = new FObjectExport(); exp.Serialize(this); ExportMap.Add(exp); } Seek(Summary.StringAssetReferencesOffset); foreach (var i in Enumerable.Range(0, Summary.StringAssetReferencesCount)) { StringAssetReferences.Add(ToFString()); } // TODO: Fixup import, fixup exports, match exports with exporter object }
public void DeserializePropertyTagValue(IAssetConverter converter) { using (BinaryReader br = new BinaryReader(converter.GetExportStream(), Encoding.UTF8, true)) { int tableIndex = br.ReadInt32(); if (tableIndex < 0) { FObjectImport import = converter.GetImportMap()[tableIndex * -1 - 1]; this.Value = new FName($"{import.ObjectName.Name} : {import.ClassPackage.Name}/{import.ClassName.Name}") { NameCount = import.ObjectName.NameCount }; } else if (tableIndex > 0) { this.Value = converter.GetExportMap()[tableIndex - 1].ObjectName; } else { this.Value = new FName("UObject"); } } }
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(); } } } }
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); }); } }
public ResolvedScriptObject(int index, Package package) : base(package, index) { _import = package.ImportMap[index]; }
public ResolvedImportObject(FObjectImport import, Package package) : base(package) { _import = import; }