/// <summary> /// The export. /// </summary> /// <param name="entry"> /// The entry. /// </param> protected override void Export(ExportEntry entry) { if (entry.IsSingleton) { this.container.RegisterType( entry.InfType, entry.ImplType, entry.Name, new ContainerControlledLifetimeManager()); } else { this.container.RegisterType( entry.InfType, entry.ImplType, entry.Name); } }
void IStringSettingConvertible.Convert(string settingValue) { if (string.IsNullOrWhiteSpace(settingValue)) { return; } XDocument doc = XDocument.Parse(settingValue); foreach (var exportE in doc.Root.Elements("Export")) { ExportEntry evm = new ExportEntry(); evm.Name = exportE.Attribute("Name").Value; evm.IsEnabled = bool.Parse(exportE.Attribute("IsEnabled").Value); Exports.Add(evm); } }
protected override void Export(ExportEntry entry) { IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle> regBuilder = this.builder.RegisterType(entry.ImplType); if (string.IsNullOrEmpty(entry.Name)) { regBuilder.As(entry.InfType); } else { regBuilder.Named(entry.Name, entry.InfType); } if (entry.IsSingleton) { regBuilder.SingleInstance(); } }
public void Save(string filePath = null) { try { DebugLog.PrintLn("Writing Header...", true); MemoryStream m = new MemoryStream(); m.Write(BitConverter.GetBytes(Header.magic), 0, 4); m.Write(BitConverter.GetBytes(Header.ver1), 0, 2); m.Write(BitConverter.GetBytes(Header.ver2), 0, 2); m.Write(BitConverter.GetBytes(Header.HeaderLength), 0, 4); WriteUString(Header.Group, m); if (GeneralInfo.compressed) { m.Write(BitConverter.GetBytes(Header.Flags ^ 0x02000000), 0, 4); } else { m.Write(BitConverter.GetBytes(Header.Flags), 0, 4); } m.Write(BitConverter.GetBytes(Header.unk1), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(Header.unk2), 0, 4); m.Write(BitConverter.GetBytes(Header.unk3), 0, 4); m.Write(BitConverter.GetBytes(Header.unk4), 0, 4); m.Write(Header.GUID, 0, 16); m.Write(BitConverter.GetBytes(Header.Generations.Count), 0, 4); foreach (Generation g in Header.Generations) { m.Write(BitConverter.GetBytes(g.ExportCount), 0, 4); m.Write(BitConverter.GetBytes(g.ImportCount), 0, 4); m.Write(BitConverter.GetBytes(g.NetObjCount), 0, 4); } m.Write(BitConverter.GetBytes(Header.EngineVersion), 0, 4); m.Write(BitConverter.GetBytes(Header.CookerVersion), 0, 4); m.Write(BitConverter.GetBytes(Header.unk5), 0, 4); m.Write(BitConverter.GetBytes(Header.unk6), 0, 4); m.Write(BitConverter.GetBytes(Header.CompressionFlag), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(Header.unk7), 0, 4); m.Write(BitConverter.GetBytes(Header.unk8), 0, 4); DebugLog.PrintLn("Writing Name Table...", true); Header.NameOffset = (uint)m.Position; Header.NameCount = (uint)Names.Count; foreach (string s in Names) { WriteUString(s, m); } DebugLog.PrintLn("Writing Import Table...", true); Header.ImportOffset = (uint)m.Position; Header.ImportCount = (uint)Imports.Count; foreach (ImportEntry e in Imports) { m.Write(BitConverter.GetBytes(e.idxPackage), 0, 4); m.Write(BitConverter.GetBytes(e.Unk1), 0, 4); m.Write(BitConverter.GetBytes(e.idxClass), 0, 4); m.Write(BitConverter.GetBytes(e.Unk2), 0, 4); m.Write(BitConverter.GetBytes(e.idxLink), 0, 4); m.Write(BitConverter.GetBytes(e.idxName), 0, 4); m.Write(BitConverter.GetBytes(e.Unk3), 0, 4); } DebugLog.PrintLn("Writing Export Table...", true); Header.ExportOffset = (uint)m.Position; Header.ExportCount = (uint)Exports.Count; for (int i = 0; i < Exports.Count; i++) { ExportEntry e = Exports[i]; e._infooffset = (uint)m.Position; Exports[i] = e; m.Write(BitConverter.GetBytes(e.idxClass), 0, 4); m.Write(BitConverter.GetBytes(e.idxParent), 0, 4); m.Write(BitConverter.GetBytes(e.idxLink), 0, 4); m.Write(BitConverter.GetBytes(e.idxName), 0, 4); m.Write(BitConverter.GetBytes(e.Index), 0, 4); m.Write(BitConverter.GetBytes(e.idxArchetype), 0, 4); m.Write(BitConverter.GetBytes(e.Unk1), 0, 4); m.Write(BitConverter.GetBytes(e.ObjectFlags), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(0), 0, 4); m.Write(BitConverter.GetBytes(e.Unk2), 0, 4); m.Write(BitConverter.GetBytes(e.Unk3.Length), 0, 4); foreach (int j in e.Unk3) { m.Write(BitConverter.GetBytes(j), 0, 4); } m.Write(BitConverter.GetBytes(e.Unk4), 0, 4); m.Write(BitConverter.GetBytes(e.Unk5), 0, 4); m.Write(BitConverter.GetBytes(e.Unk6), 0, 4); m.Write(BitConverter.GetBytes(e.Unk7), 0, 4); m.Write(BitConverter.GetBytes(e.Unk8), 0, 4); } DebugLog.PrintLn("Writing Free Zone...", true); int FreeZoneSize = (int)Header.FreeZoneEnd - (int)Header.FreeZoneStart; Header.FreeZoneStart = (uint)m.Position; m.Write(new byte[FreeZoneSize], 0, FreeZoneSize); Header.FreeZoneEnd = Header.HeaderLength = (uint)m.Position; DebugLog.PrintLn("Writing Export Data...", true); for (int i = 0; i < Exports.Count; i++) { ExportEntry e = Exports[i]; byte[] buff = GetObjectData(i); e.Dataoffset = (int)m.Position; e.Datasize = buff.Length; m.Write(buff, 0, buff.Length); long pos = m.Position; m.Seek(e._infooffset + 32, 0); m.Write(BitConverter.GetBytes(e.Datasize), 0, 4); m.Write(BitConverter.GetBytes(e.Dataoffset), 0, 4); m.Seek(pos, 0); } DebugLog.PrintLn("Updating Header...", true); m.Seek(8, 0); m.Write(BitConverter.GetBytes(Header.HeaderLength), 0, 4); m.Seek(24 + (Header.Group.Length + 1) * 2, 0); m.Write(BitConverter.GetBytes(Header.NameCount), 0, 4); m.Write(BitConverter.GetBytes(Header.NameOffset), 0, 4); m.Write(BitConverter.GetBytes(Header.ExportCount), 0, 4); m.Write(BitConverter.GetBytes(Header.ExportOffset), 0, 4); m.Write(BitConverter.GetBytes(Header.ImportCount), 0, 4); m.Write(BitConverter.GetBytes(Header.ImportOffset), 0, 4); m.Write(BitConverter.GetBytes(Header.FreeZoneStart), 0, 4); m.Write(BitConverter.GetBytes(Header.FreeZoneEnd), 0, 4); DebugLog.PrintLn("Done generating.", true); if (Source != null) { Source.Close(); } if (filePath == null) { File.WriteAllBytes(GeneralInfo.filepath, m.ToArray()); } else { File.WriteAllBytes(filePath, m.ToArray()); } DebugLog.PrintLn("Done.", true); } catch (Exception ex) { DebugLog.PrintLn("PCCPACKAGE::SAVE ERROR:\n" + ex.Message); } }
private static bool CanRandomize(ExportEntry exp) => !exp.IsDefaultObject && exp.ObjectFlags.Has(UnrealFlags.EObjectFlags.ArchetypeObject) && exp.ClassName == "SFXSkeletalMeshActorMAT" && !exp.ObjectName.Name.Contains("Dead", StringComparison.InvariantCultureIgnoreCase);
protected InterpTrack(ExportEntry export) { Export = export; TrackTitle = export.GetProperty <StrProperty>("TrackTitle")?.Value ?? export.ObjectName.Instanced; }
protected UnContainer(ExportEntry self, int superIndex, byte[] bytecode) : base(self, bytecode) { _super = superIndex == 0 ? null : _self.FileRef.GetEntry(superIndex); }
private void ReadExports(MemoryTributary fs) { DebugOutput.PrintLn("Reading Exports..."); fs.Seek(ExportOffset, SeekOrigin.Begin); Exports = new List<ExportEntry>(); for (int i = 0; i < ExportCount; i++) { long start = fs.Position; ExportEntry exp = new ExportEntry(); exp.pccRef = this; exp.infoOffset = (int)start; fs.Seek(40, SeekOrigin.Current); int count = fs.ReadValueS32(); fs.Seek(4 + count * 12, SeekOrigin.Current); count = fs.ReadValueS32(); fs.Seek(4 + count * 4, SeekOrigin.Current); fs.Seek(16, SeekOrigin.Current); long end = fs.Position; fs.Seek(start, SeekOrigin.Begin); exp.info = fs.ReadBytes((int)(end - start)); Exports.Add(exp); fs.Seek(end, SeekOrigin.Begin); if (LastExport == null || exp.DataOffset > LastExport.DataOffset) LastExport = exp; } }
public void CloneEntry(int uIndex) { if (uIndex > 0) { ExportEntry e = Exports[uIndex - 1]; ExportEntry n = new ExportEntry(); n.Data = CopyArray(GetObjectData(uIndex - 1)); n.DataLoaded = true; n.Datasize = n.Data.Length; n.idxClass = e.idxClass; n.idxParent = e.idxParent; n.idxLink = e.idxLink; n.idxName = e.idxName; n.Index = GetBiggestIndex() + 1; n.idxArchetype = e.idxArchetype; n.Unk1 = e.Unk1; n.ObjectFlags = e.ObjectFlags; n.Unk2 = e.Unk2; n.Unk3 = new int[e.Unk3.Length]; for (int i = 0; i < e.Unk3.Length; i++) n.Unk3[i] = e.Unk3[i]; n.Unk2 = e.Unk4; n.Unk2 = e.Unk5; n.Unk2 = e.Unk6; n.Unk2 = e.Unk7; n.Unk2 = e.Unk8; Exports.Add(n); Header.ExportCount++; } else { ImportEntry e = Imports[-uIndex - 1]; ImportEntry n = new ImportEntry(); n.idxPackage = e.idxPackage; n.Unk1 = e.Unk1; n.idxClass = e.idxClass; n.Unk2 = e.Unk2; n.idxLink = e.idxLink; n.idxName = e.idxName; n.Unk3 = e.Unk3; Imports.Add(n); Header.ImportCount++; } }
public static PropertyInfo getPropertyInfo(string className, string propName, bool inStruct = false, ClassInfo nonVanillaClassInfo = null, bool reSearch = true, ExportEntry containingExport = null) { if (className.StartsWith("Default__")) { className = className.Substring(9); } Dictionary <string, ClassInfo> temp = inStruct ? Structs : Classes; bool infoExists = temp.TryGetValue(className, out ClassInfo info); if (!infoExists && nonVanillaClassInfo != null) { info = nonVanillaClassInfo; infoExists = true; } if (infoExists) //|| (temp = !inStruct ? Structs : Classes).ContainsKey(className)) { //look in class properties if (info.properties.TryGetValue(propName, out var propInfo)) { return(propInfo); } //look in structs foreach (PropertyInfo p in info.properties.Values()) { if ((p.Type == PropertyType.StructProperty || p.Type == PropertyType.ArrayProperty) && reSearch) { PropertyInfo val = getPropertyInfo(p.Reference, propName, true, nonVanillaClassInfo, reSearch: false); if (val != null) { return(val); } } } //look in base class if (temp.ContainsKey(info.baseClass)) { PropertyInfo val = getPropertyInfo(info.baseClass, propName, inStruct, nonVanillaClassInfo, reSearch: true); if (val != null) { return(val); } } else { //Baseclass may be modified as well... if (containingExport != null && containingExport.idxSuperClass > 0) { //Class parent is in this file. Generate class parent info and attempt refetch ExportEntry parentExport = containingExport.FileRef.getUExport(containingExport.idxSuperClass); return(getPropertyInfo(parentExport.SuperClassName, propName, inStruct, generateClassInfo(parentExport), reSearch: true, parentExport)); } } } //if (reSearch) //{ // PropertyInfo reAttempt = getPropertyInfo(className, propName, !inStruct, nonVanillaClassInfo, reSearch: false); // return reAttempt; //will be null if not found. //} return(null); }
//public List<TextureParam> Textures = new List<TextureParam>(); //public struct TextureParam //{ // public int TexIndex; // public string Desc; //} public MaterialInstanceConstant(ExportEntry export, PackageCache assetCache = null) { Export = export; ReadMaterial(export, assetCache); }
public override void LoadExport(ExportEntry exportEntry) { CurrentLoadedExport = exportEntry; var props = exportEntry.GetProperties(); List <ParticleSystemNode> rootNodes = new List <ParticleSystemNode>(); var emitters = props.GetProp <ArrayProperty <ObjectProperty> >("Emitters"); foreach (var emitter in emitters) { if (emitter.Value != 0) { if (CurrentLoadedExport.FileRef.IsUExport(emitter.Value)) { var emitterExport = CurrentLoadedExport.FileRef.GetUExport(emitter.Value); var emitterName = emitterExport.GetProperty <NameProperty>("EmitterName"); string header = emitterName?.Value.Name ?? "Emitter"; ParticleSystemNode p = new ParticleSystemNode { Entry = emitterExport, Header = $"{emitterExport.UIndex} {header}" }; rootNodes.Add(p); var emitterLODs = emitterExport.GetProperty <ArrayProperty <ObjectProperty> >("LODLevels"); int lodNumber = 0; if (emitterLODs != null) { foreach (var lod in emitterLODs) { var lodExport = CurrentLoadedExport.FileRef.GetUExport(lod.Value); ParticleSystemNode psLod = new ParticleSystemNode { Entry = lodExport, Header = $"LOD {lodNumber}: {lodExport.UIndex} {lodExport.InstancedFullPath}" }; p.Children.Add(psLod); { var requiredModule = (ExportEntry)lodExport.GetProperty <ObjectProperty>("RequiredModule")?.ResolveToEntry(CurrentLoadedExport.FileRef); if (requiredModule != null) { ParticleSystemNode reqModule = new ParticleSystemNode { Entry = requiredModule, Header = $"Required Module: {requiredModule.UIndex} {requiredModule.InstancedFullPath}" }; psLod.Children.Add(reqModule); var materialEntry = requiredModule.GetProperty <ObjectProperty>("Material")?.ResolveToEntry(CurrentLoadedExport.FileRef); if (materialEntry != null) { ParticleSystemNode matNode = new ParticleSystemNode { Entry = materialEntry, Header = $"Material: {materialEntry.UIndex} {materialEntry.InstancedFullPath}" }; reqModule.Children.Add(matNode); } } } var typeDataExport = (ExportEntry)lodExport.GetProperty <ObjectProperty>("TypeDataModule")?.ResolveToEntry(CurrentLoadedExport.FileRef); if (typeDataExport != null) { ParticleSystemNode typeModuleNode = new ParticleSystemNode { Entry = typeDataExport, Header = $"Type Data Module: {typeDataExport.UIndex} {typeDataExport.InstancedFullPath}" }; psLod.Children.Add(typeModuleNode); var meshes = typeDataExport.GetProperty <ArrayProperty <ObjectProperty> >("m_Meshes"); if (meshes != null) { int meshIndex = 0; foreach (var mesh in meshes) { var meshExp = mesh.ResolveToEntry(CurrentLoadedExport.FileRef); if (meshExp != null) { ParticleSystemNode meshNode = new ParticleSystemNode { Entry = meshExp, Header = $"Mesh {meshIndex}: {meshExp.UIndex} {meshExp.InstancedFullPath}" }; typeModuleNode.Children.Add(meshNode); } meshIndex++; } } } var modules = lodExport.GetProperty <ArrayProperty <ObjectProperty> >("Modules"); if (modules != null) { int modIndex = 0; foreach (var module in modules) { var moduleExp = module.ResolveToEntry(CurrentLoadedExport.FileRef); if (moduleExp != null) { ParticleSystemNode moduleNode = new ParticleSystemNode { Entry = moduleExp, Header = $"Module {modIndex}: {moduleExp.UIndex} {moduleExp.InstancedFullPath}" }; psLod.Children.Add(moduleNode); GenerateNode(moduleNode); } modIndex++; } } lodNumber++; } } } } } ParticleNodes.ReplaceAll(rootNodes); }
public static ArrayType getArrayType(string className, string propName, bool inStruct = false, ExportEntry export = null) { PropertyInfo p = getPropertyInfo(className, propName, inStruct, containingExport: export) ?? getPropertyInfo(className, propName, !inStruct, containingExport: export); if (p == null && export != null) { if (export.ClassName != "Class" && export.idxClass > 0) { export = export.FileRef.Exports[export.idxClass - 1]; //make sure you get actual class } if (export.ClassName == "Class") { ClassInfo currentInfo = generateClassInfo(export); currentInfo.baseClass = export.SuperClassName; p = getPropertyInfo(className, propName, inStruct, currentInfo, containingExport: export) ?? getPropertyInfo(className, propName, !inStruct, currentInfo, containingExport: export); } } return(getArrayType(p)); }
//Random distributions "Op" // // 0 = NONE // 1 = Random // 2 = Extremes (ends) // 3 = Random (range) take random within range public override bool CanParse(ExportEntry exportEntry) => !exportEntry.IsDefaultObject && exportEntry.ClassName == "ParticleSystem";
/// <summary> /// PCCObject class constructor. It also load namelist, importlist and exportinfo (not exportdata) from pcc file /// </summary> /// <param name="pccFilePath">full path + file name of desired pcc file.</param> public PCCObject(string pccFilePath, bool fullFileInMemory = false) { Loaded = true; pccFileName = Path.GetFullPath(pccFilePath); using (FileStream pccStream = File.OpenRead(pccFileName)) { Names = new List<string>(); Imports = new List<ImportEntry>(); Exports = new List<ExportEntry>(); pccStream.Read(header, 0, header.Length); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) { throw new FormatException("not a pcc file"); } // BitConverter isn't working?!?! if (magic == 0x9E2A83C1) BitConverter.IsLittleEndian = true; else BitConverter.IsLittleEndian = true; if (lowVers != 684 && highVers != 194) { throw new FormatException("unsupported version"); } Stream listsStream; if (bCompressed) { // seeks the blocks info position pccStream.Seek(idxOffsets + 60, SeekOrigin.Begin); int generator = pccStream.ReadValueS32(); pccStream.Seek((generator * 12) + 20, SeekOrigin.Current); int blockCount = pccStream.ReadValueS32(); blockList = new List<Block>(); // creating the Block list for (int i = 0; i < blockCount; i++) { Block temp = new Block(); temp.uncOffset = pccStream.ReadValueS32(); temp.uncSize = pccStream.ReadValueS32(); temp.cprOffset = pccStream.ReadValueS32(); temp.cprSize = pccStream.ReadValueS32(); blockList.Add(temp); } // correcting the header, in case there's need to be saved Buffer.BlockCopy(BitConverter.GetBytes((int)0), 0, header, header.Length - 12, sizeof(int)); pccStream.Read(header, header.Length - 8, 8); headerEnd = (int)pccStream.Position; // copying the extraNamesList int extraNamesLenght = blockList[0].cprOffset - headerEnd; if (extraNamesLenght > 0) { extraNamesList = new byte[extraNamesLenght]; pccStream.Read(extraNamesList, 0, extraNamesLenght); //FileStream fileStream = File.Create(Path.GetDirectoryName(pccFileName) + "\\temp.bin"); //fileStream.Write(extraNamesList, 0, extraNamesLenght); //MessageBox.Show("posizione: " + pccStream.Position.ToString("X8")); } // decompress first block that holds infos about names, imports and exports pccStream.Seek(blockList[0].cprOffset, SeekOrigin.Begin); byte[] uncBlock = ZBlock.Decompress(pccStream, blockList[0].cprSize); // write decompressed block inside temporary stream listsStream = new MemoryStream(); listsStream.Seek(blockList[0].uncOffset, SeekOrigin.Begin); listsStream.Write(uncBlock, 0, uncBlock.Length); } else { listsStream = pccStream; headerEnd = (int)NameOffset; // copying the extraNamesList int extraNamesLenght = headerEnd - headerSize; if (extraNamesLenght > 0) { extraNamesList = new byte[extraNamesLenght]; listsStream.Seek(headerSize, SeekOrigin.Begin); listsStream.Read(extraNamesList, 0, extraNamesLenght); //FileStream fileStream = File.Create(Path.GetDirectoryName(pccFileName) + "\\temp.bin"); //fileStream.Write(extraNamesList, 0, extraNamesLenght); //MessageBox.Show("posizione: " + pccStream.Position.ToString("X8")); } } /*if(bExtraNamesList) { int extraNamesListSize = namesOffset - headerEnd; extraNamesList = new byte[extraNamesListSize]; pccStream.Seek(headerEnd, SeekOrigin.Begin); pccStream.Read(extraNamesList, 0, extraNamesList.Length); }*/ // fill names list listsStream.Seek(NameOffset, SeekOrigin.Begin); for (int i = 0; i < NameCount; i++) { long currOffset = listsStream.Position; int strLength = listsStream.ReadValueS32(); string str = listsStream.ReadString(strLength * -2, true, Encoding.Unicode); //Debug.WriteLine("Read name "+i+" "+str+" length: " + strLength+", offset: "+currOffset); Names.Add(str); } //Debug.WriteLine("Names done. Current offset: "+listsStream.Position); //Debug.WriteLine("Import Offset: " + ImportOffset); // fill import list Console.Out.WriteLine("IMPORT OFFSET: " + ImportOffset); listsStream.Seek(ImportOffset, SeekOrigin.Begin); byte[] buffer = new byte[ImportEntry.byteSize]; for (int i = 0; i < ImportCount; i++) { long offset = listsStream.Position; ImportEntry e = new ImportEntry(this, listsStream); Imports.Add(e); //Debug.WriteLine("Read import " + i + " " + e.ObjectName + ", offset: " + offset); } Debug.WriteLine("Imports done. Current offset: " + listsStream.Position); Debug.WriteLine("Export Offset: " + ExportOffset); // fill export list (only the headers, not the data) listsStream.Seek(ExportOffset, SeekOrigin.Begin); Console.Out.WriteLine("Export OFFSET: " + ImportOffset); for (int i = 0; i < ExportCount; i++) { uint expInfoOffset = (uint)listsStream.Position; listsStream.Seek(44, SeekOrigin.Current); int count = listsStream.ReadValueS32(); listsStream.Seek(-48, SeekOrigin.Current); int expInfoSize = 68 + (count * 4); buffer = new byte[expInfoSize]; listsStream.Read(buffer, 0, buffer.Length); ExportEntry e = new ExportEntry(this, buffer, expInfoOffset); //Debug.WriteLine("Read export " + i + " " + e.ObjectName + ", offset: " + expInfoOffset+ ", size: "+expInfoSize); Exports.Add(e); } } Debug.WriteLine(getMetadataString()); }
/// <summary> /// given export data offset, the function recovers it from the file. /// </summary> /// <param name="offset">offset position of desired export data</param> private void getData(int offset, ExportEntry exp = null) { byte[] buffer; if (bCompressed) { Block selected = blockList.Find(block => block.uncOffset <= offset && block.uncOffset + block.uncSize > offset); byte[] uncBlock; using (FileStream pccStream = File.OpenRead(pccFileName)) { pccStream.Seek(selected.cprOffset, SeekOrigin.Begin); uncBlock = ZBlock.Decompress(pccStream, selected.cprSize); // the selected block has been read selected.bRead = true; } // fill all the exports data extracted from the uncBlock foreach (ExportEntry expInfo in Exports) { if (expInfo.DataOffset >= selected.uncOffset && expInfo.DataOffset + expInfo.DataSize <= selected.uncOffset + selected.uncSize) { buffer = new byte[expInfo.DataSize]; Buffer.BlockCopy(uncBlock, expInfo.DataOffset - selected.uncOffset, buffer, 0, expInfo.DataSize); expInfo.Data = buffer; } } } else { ExportEntry expSelect; if (exp == null) { int expIndex = Exports.FindIndex(export => export.DataOffset <= offset && export.DataOffset + export.DataSize > offset); expSelect = Exports[expIndex]; } else { expSelect = exp; } using (FileStream pccStream = File.OpenRead(pccFileName)) { buffer = new byte[expSelect.DataSize]; pccStream.Seek(expSelect.DataOffset, SeekOrigin.Begin); pccStream.Read(buffer, 0, buffer.Length); expSelect.Data = buffer; } } }
public virtual void Dispose() { g = null; pcc = null; export = null; }
private static PropertyInfo getProperty(ExportEntry entry) { IMEPackage pcc = entry.FileRef; string reference = null; PropertyType type; switch (entry.ClassName) { case "IntProperty": type = PropertyType.IntProperty; break; case "StringRefProperty": type = PropertyType.StringRefProperty; break; case "FloatProperty": type = PropertyType.FloatProperty; break; case "BoolProperty": type = PropertyType.BoolProperty; break; case "StrProperty": type = PropertyType.StrProperty; break; case "NameProperty": type = PropertyType.NameProperty; break; case "DelegateProperty": type = PropertyType.DelegateProperty; break; case "ClassProperty": case "ObjectProperty": case "ComponentProperty": type = PropertyType.ObjectProperty; reference = pcc.getObjectName(BitConverter.ToInt32(entry.Data, entry.Data.Length - 4)); break; case "StructProperty": type = PropertyType.StructProperty; reference = pcc.getObjectName(BitConverter.ToInt32(entry.Data, entry.Data.Length - 4)); break; case "BioMask4Property": case "ByteProperty": type = PropertyType.ByteProperty; reference = pcc.getObjectName(BitConverter.ToInt32(entry.Data, entry.Data.Length - 4)); break; case "ArrayProperty": type = PropertyType.ArrayProperty; PropertyInfo arrayTypeProp = getProperty(pcc.getUExport(BitConverter.ToInt32(entry.Data, 44))); if (arrayTypeProp != null) { switch (arrayTypeProp.Type) { case PropertyType.ObjectProperty: case PropertyType.StructProperty: case PropertyType.ArrayProperty: reference = arrayTypeProp.Reference; break; case PropertyType.ByteProperty: //if (arrayTypeProp.reference == "") if (arrayTypeProp.Reference == "Class") { reference = arrayTypeProp.Type.ToString(); } else { reference = arrayTypeProp.Reference; } break; case PropertyType.IntProperty: case PropertyType.FloatProperty: case PropertyType.NameProperty: case PropertyType.BoolProperty: case PropertyType.StrProperty: case PropertyType.StringRefProperty: case PropertyType.DelegateProperty: reference = arrayTypeProp.Type.ToString(); break; case PropertyType.None: case PropertyType.Unknown: default: Debugger.Break(); return(null); } } else { return(null); } break; case "InterfaceProperty": default: return(null); } bool transient = ((UnrealFlags.EPropertyFlags)BitConverter.ToUInt64(entry.Data, 24)).HasFlag(UnrealFlags.EPropertyFlags.Transient); return(new PropertyInfo(type, reference, transient)); }
/// <summary> /// given export data offset, the function recovers it from the file. /// </summary> /// <param name="offset">offset position of desired export data</param> private void getData(int offset, ExportEntry exp = null) { byte[] buffer; ExportEntry expSelect; if (exp == null) { int expIndex = Exports.FindIndex(export => export.DataOffset <= offset && export.DataOffset + export.DataSize > offset); expSelect = Exports[expIndex]; } else { expSelect = exp; } using (FileStream udkStream = File.OpenRead(FileName)) { buffer = new byte[expSelect.DataSize]; udkStream.Seek(expSelect.DataOffset, SeekOrigin.Begin); udkStream.Read(buffer, 0, buffer.Length); expSelect.Data = buffer; } }
/// <summary> /// Add an export entry. /// </summary> /// <param name="entry"> /// An entry to add. /// </param> protected void Add(ExportEntry entry) { this.exportEntries.Add(entry); }
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); }
private static void RepointAllVariableReferencesToNode(ExportEntry targetNode, ExportEntry newNode, List <ExportEntry> exceptions = null) { var sequence = targetNode.FileRef.GetUExport(targetNode.GetProperty <ObjectProperty>("ParentSequence").Value); var sequenceObjects = sequence.GetProperty <ArrayProperty <ObjectProperty> >("SequenceObjects"); foreach (var seqObjRef in sequenceObjects) { var saveProps = false; var seqObj = targetNode.FileRef.GetUExport(seqObjRef.Value); var props = seqObj.GetProperties(); var variableLinks = props.GetProp <ArrayProperty <StructProperty> >("VariableLinks"); if (variableLinks != null) { foreach (var variableLink in variableLinks) { var linkedVars = variableLink.GetProp <ArrayProperty <ObjectProperty> >("LinkedVariables"); if (linkedVars != null) { foreach (var linkedVar in linkedVars) { if (linkedVar.Value == targetNode.UIndex) { linkedVar.Value = newNode.UIndex; //repoint saveProps = true; } } } } } if (saveProps) { seqObj.WriteProperties(props); } } }
/// <summary> /// Export an entry for import later. /// </summary> /// <param name="entry"> /// The entry to export. /// </param> protected abstract void Export(ExportEntry entry);
internal static void SetLocation(ExportEntry bioPawn, Vector3 position) { SetLocation(bioPawn, position.X, position.Y, position.Z); }
private static bool CanRandomize(ExportEntry export) => !export.IsDefaultObject && (export.ClassName == @"SpotLightComponent" || export.ClassName == @"PointLightComponent" || export.ClassName == @"DirectionalLightComponent" || export.ClassName == @"SkyLightComponent");
public ExportEntry cloneExport(int exportid, string newPackageName, string newObjectName) { ExportEntry cloneObj = Exports[exportid-1]; ExportEntry exp = new ExportEntry(); exp.pccRef = this; exp.Info = cloneObj.Info; listsStream.Seek(ExportDataEnd, SeekOrigin.Begin); exp.DataSize = cloneObj.DataSize; exp.DataOffset = (int)listsStream.Position; exp.ClassName = cloneObj.ClassName; byte[] data = cloneObj.Data; listsStream.Seek(ExportDataEnd, SeekOrigin.Begin); listsStream.WriteBytes(data); exp.exportid = Exports.Count()+1; exp.setPackageName(newPackageName); exp.setObjectName(newObjectName); LastExport = exp; Exports.Add(exp); return exp; }
public InterpTrackMove(ExportEntry export) : base(export) { }
public override bool CanParse(ExportEntry exportEntry) { return((exportEntry.ClassName == "Function" || exportEntry.ClassName == "State") && exportEntry.FileRef.Game != MEGame.UDK); }
protected UnBytecodeOwner(ExportEntry self, byte[] bytecode) { _self = self; _bytecode = bytecode; }
public static ObjectBinary From(ExportEntry export) { if (export.IsDefaultObject) { //DefaultObjects don't have binary return(null); } string className = export.ClassName; if (export.IsA("BioPawn")) { //way, waaay too many subclasses of BioPawn to put in the switch statement, so we take care of it here className = "BioPawn"; } switch (className) { case "AnimSequence": return(From <AnimSequence>(export)); case "BioStage": return(From <BioStage>(export)); case "Level": return(From <Level>(export)); case "World": return(From <World>(export)); case "Model": return(From <Model>(export)); case "Polys": return(From <Polys>(export)); case "DecalMaterial": case "Material": return(From <Material>(export)); case "MaterialInstanceConstant": case "MaterialInstanceTimeVarying": if (export.GetProperty <BoolProperty>("bHasStaticPermutationResource")?.Value == true) { return(From <MaterialInstance>(export)); } return(Array.Empty <byte>()); case "FracturedStaticMesh": return(From <FracturedStaticMesh>(export)); case "StaticMesh": return(From <StaticMesh>(export)); case "SkeletalMesh": case "BioSocketSupermodel": return(From <SkeletalMesh>(export)); case "CoverMeshComponent": case "InteractiveFoliageComponent": case "SplineMeshComponent": case "FracturedStaticMeshComponent": case "StaticMeshComponent": return(From <StaticMeshComponent>(export)); case "DecalComponent": return(From <DecalComponent>(export)); case "Terrain": return(From <Terrain>(export)); case "TerrainComponent": return(From <TerrainComponent>(export)); case "FluidSurfaceComponent": return(From <FluidSurfaceComponent>(export)); case "ModelComponent": return(From <ModelComponent>(export)); case "BioDynamicAnimSet": return(From <BioDynamicAnimSet>(export)); case "BioPawn": return(From <BioPawn>(export)); case "PrefabInstance": return(From <PrefabInstance>(export)); case "Class": return(From <UClass>(export)); case "State": return(From <UState>(export)); case "Function": return(From <UFunction>(export)); case "Enum": return(From <UEnum>(export)); case "Const": return(From <UConst>(export)); case "ScriptStruct": return(From <UScriptStruct>(export)); case "IntProperty": return(From <UIntProperty>(export)); case "BoolProperty": return(From <UBoolProperty>(export)); case "FloatProperty": return(From <UFloatProperty>(export)); case "NameProperty": return(From <UNameProperty>(export)); case "StrProperty": return(From <UStrProperty>(export)); case "StringRefProperty": return(From <UStringRefProperty>(export)); case "ByteProperty": return(From <UByteProperty>(export)); case "ObjectProperty": return(From <UObjectProperty>(export)); case "ComponentProperty": return(From <UComponentProperty>(export)); case "InterfaceProperty": return(From <UInterfaceProperty>(export)); case "ArrayProperty": return(From <UArrayProperty>(export)); case "StructProperty": return(From <UStructProperty>(export)); case "BioMask4Property": return(From <UBioMask4Property>(export)); case "MapProperty": return(From <UMapProperty>(export)); case "ClassProperty": return(From <UClassProperty>(export)); case "DelegateProperty": return(From <UDelegateProperty>(export)); case "ShaderCache": return(From <ShaderCache>(export)); case "StaticMeshCollectionActor": return(From <StaticMeshCollectionActor>(export)); case "StaticLightCollectionActor": return(From <StaticLightCollectionActor>(export)); case "WwiseEvent": return(From <WwiseEvent>(export)); case "WwiseStream": return(From <WwiseStream>(export)); case "WwiseBank": return(From <WwiseBank>(export)); case "BioGestureRuntimeData": return(From <BioGestureRuntimeData>(export)); case "LightMapTexture2D": return(From <LightMapTexture2D>(export)); case "Texture2D": case "ShadowMapTexture2D": case "TerrainWeightMapTexture": case "TextureFlipBook": return(From <UTexture2D>(export)); case "GuidCache": return(From <GuidCache>(export)); case "FaceFXAnimSet": return(From <FaceFXAnimSet>(export)); case "Bio2DA": case "Bio2DANumberedRows": return(From <Bio2DABinary>(export)); case "BioMorphFace": return(From <BioMorphFace>(export)); case "MorphTarget": return(From <MorphTarget>(export)); case "SFXMorphFaceFrontEndDataSource": return(From <SFXMorphFaceFrontEndDataSource>(export)); case "PhysicsAssetInstance": return(From <PhysicsAssetInstance>(export)); case "DirectionalLightComponent": case "PointLightComponent": case "SkyLightComponent": case "SphericalHarmonicLightComponent": case "SpotLightComponent": case "DominantSpotLightComponent": case "DominantPointLightComponent": case "DominantDirectionalLightComponent": return(From <LightComponent>(export)); case "ShadowMap1D": return(From <ShadowMap1D>(export)); case "BioTlkFileSet": return(From <BioTlkFileSet>(export)); case "RB_BodySetup": return(From <RB_BodySetup>(export)); case "BrushComponent": return(From <BrushComponent>(export)); case "ForceFeedbackWaveform": return(From <ForceFeedbackWaveform>(export)); case "SoundCue": return(From <SoundCue>(export)); case "SoundNodeWave": return(From <SoundNodeWave>(export)); case "ObjectRedirector": return(From <ObjectRedirector>(export)); case "TextureMovie": return(From <TextureMovie>(export)); default: return(null); } }
private void ReadExportTable() { try { DebugLog.PrintLn("Reading Export Table..."); Exports = new List <ExportEntry>(); if (GeneralInfo.compressed) { UncompressRange(Header._offsetCompFlagEnd + 0xC, Header.HeaderLength - (Header._offsetCompFlagEnd + 0xC)); Header.DeCompBuffer.Seek(Header.ExportOffset, 0); for (int i = 0; i < Header.ExportCount; i++) { ExportEntry e = new ExportEntry(); e.idxClass = ReadInt(Header.DeCompBuffer); e.idxParent = ReadInt(Header.DeCompBuffer); e.idxLink = ReadInt(Header.DeCompBuffer); e.idxName = ReadInt(Header.DeCompBuffer); e.Index = ReadInt(Header.DeCompBuffer); e.idxArchetype = ReadInt(Header.DeCompBuffer); e.Unk1 = ReadInt(Header.DeCompBuffer); e.ObjectFlags = ReadInt(Header.DeCompBuffer); e.Datasize = ReadInt(Header.DeCompBuffer); e.Dataoffset = ReadInt(Header.DeCompBuffer); long pos = Header.DeCompBuffer.Position; if (!GeneralInfo.loadfull) { e.DataLoaded = false; } else { e.Data = GetObjectData(e.Dataoffset, e.Datasize); e.DataLoaded = true; } Header.DeCompBuffer.Seek(pos, 0); e.Unk2 = ReadInt(Header.DeCompBuffer); int count = ReadInt(Header.DeCompBuffer); e.Unk3 = new int[count]; for (int j = 0; j < count; j++) { e.Unk3[j] = ReadInt(Header.DeCompBuffer); } e.Unk4 = ReadInt(Header.DeCompBuffer); e.Unk5 = ReadInt(Header.DeCompBuffer); e.Unk6 = ReadInt(Header.DeCompBuffer); e.Unk7 = ReadInt(Header.DeCompBuffer); e.Unk8 = ReadInt(Header.DeCompBuffer); Exports.Add(e); } } else { Source.Seek(Header.ExportOffset, 0); for (int i = 0; i < Header.ExportCount; i++) { ExportEntry e = new ExportEntry(); e.idxClass = ReadInt(Source); e.idxParent = ReadInt(Source); e.idxLink = ReadInt(Source); e.idxName = ReadInt(Source); e.Index = ReadInt(Source); e.idxArchetype = ReadInt(Source); e.Unk1 = ReadInt(Source); e.ObjectFlags = ReadInt(Source); e.Datasize = ReadInt(Source); e.Dataoffset = ReadInt(Source); long pos = Source.Position; if (!GeneralInfo.loadfull) { e.DataLoaded = false; } else { e.Data = GetObjectData(e.Dataoffset, e.Datasize); e.DataLoaded = true; } Source.Seek(pos, 0); e.Unk2 = ReadInt(Source); int count = ReadInt(Source); e.Unk3 = new int[count]; for (int j = 0; j < count; j++) { e.Unk3[j] = ReadInt(Source); } e.Unk4 = ReadInt(Source); e.Unk5 = ReadInt(Source); e.Unk6 = ReadInt(Source); e.Unk7 = ReadInt(Source); e.Unk8 = ReadInt(Source); Exports.Add(e); } } DebugLog.PrintLn("Done."); } catch (Exception ex) { DebugLog.PrintLn("PCCPACKAGE::READEXPORTTABLE ERROR:\n" + ex.Message); } }
public static void CreateReachSpec(ExportEntry startNode, bool createTwoWay, ExportEntry destinationNode, string reachSpecClass, ReachSpecSize size, PropertyCollection externalGUIDProperties = null) { IMEPackage Pcc = startNode.FileRef; ExportEntry reachSpectoClone = Pcc.Exports.FirstOrDefault(x => x.ClassName == "ReachSpec"); if (externalGUIDProperties != null) //EXTERNAL { //external node //Debug.WriteLine("Num Exports: " + pcc.Exports.Count); if (reachSpectoClone != null) { ExportEntry outgoingSpec = reachSpectoClone.Clone(); Pcc.AddExport(outgoingSpec); IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type. outgoingSpec.Class = reachSpecClassImp; outgoingSpec.ObjectName = reachSpecClassImp.ObjectName; var properties = outgoingSpec.GetProperties(); ObjectProperty outgoingSpecStartProp = properties.GetProp <ObjectProperty>("Start"); //START StructProperty outgoingEndStructProp = properties.GetProp <StructProperty>("End"); //Embeds END ObjectProperty outgoingSpecEndProp = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END outgoingSpecStartProp.Value = startNode.UIndex; outgoingSpecEndProp.Value = 0; var endGuid = outgoingEndStructProp.GetProp <StructProperty>("Guid"); endGuid.Properties = externalGUIDProperties; //set the other guid values to our guid values //Add to source node prop ArrayProperty <ObjectProperty> PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList"); PathList.Add(new ObjectProperty(outgoingSpec.UIndex)); startNode.WriteProperty(PathList); outgoingSpec.WriteProperties(properties); //Write Spec Size SharedPathfinding.SetReachSpecSize(outgoingSpec, size.SpecRadius, size.SpecHeight); //Reindex reachspecs. SharedPathfinding.ReindexMatchingObjects(outgoingSpec); } } else { //Debug.WriteLine("Source Node: " + startNode.Index); //Debug.WriteLine("Num Exports: " + pcc.Exports.Count); //int outgoingSpec = pcc.ExportCount; //int incomingSpec = pcc.ExportCount + 1; if (reachSpectoClone != null) { ExportEntry outgoingSpec = reachSpectoClone.Clone(); Pcc.AddExport(outgoingSpec); ExportEntry incomingSpec = null; if (createTwoWay) { incomingSpec = reachSpectoClone.Clone(); Pcc.AddExport(incomingSpec); } IEntry reachSpecClassImp = GetEntryOrAddImport(Pcc, reachSpecClass); //new class type. outgoingSpec.Class = reachSpecClassImp; outgoingSpec.ObjectName = reachSpecClassImp.ObjectName; var outgoingSpecProperties = outgoingSpec.GetProperties(); if (reachSpecClass == "Engine.SlotToSlotReachSpec") { outgoingSpecProperties.Add(new ByteProperty(1, "SpecDirection")); //We might need to find a way to support this edit } //Debug.WriteLine("Outgoing UIndex: " + outgoingSpecExp.UIndex); ObjectProperty outgoingSpecStartProp = outgoingSpecProperties.GetProp <ObjectProperty>("Start"); //START StructProperty outgoingEndStructProp = outgoingSpecProperties.GetProp <StructProperty>("End"); //Embeds END ObjectProperty outgoingSpecEndProp = outgoingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(outgoingSpec)); //END outgoingSpecStartProp.Value = startNode.UIndex; outgoingSpecEndProp.Value = destinationNode.UIndex; //Add to source node prop var PathList = startNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList"); PathList.Add(new ObjectProperty(outgoingSpec.UIndex)); startNode.WriteProperty(PathList); //Write Spec Size SetReachSpecSize(outgoingSpecProperties, size.SpecRadius, size.SpecHeight); outgoingSpec.WriteProperties(outgoingSpecProperties); if (createTwoWay) { incomingSpec.Class = reachSpecClassImp; incomingSpec.ObjectName = reachSpecClassImp.ObjectName; var incomingSpecProperties = incomingSpec.GetProperties(); if (reachSpecClass == "Engine.SlotToSlotReachSpec") { incomingSpecProperties.Add(new ByteProperty(2, "SpecDirection")); } ObjectProperty incomingSpecStartProp = incomingSpecProperties.GetProp <ObjectProperty>("Start"); //START StructProperty incomingEndStructProp = incomingSpecProperties.GetProp <StructProperty>("End"); //Embeds END ObjectProperty incomingSpecEndProp = incomingEndStructProp.Properties.GetProp <ObjectProperty>(SharedPathfinding.GetReachSpecEndName(incomingSpec)); //END incomingSpecStartProp.Value = destinationNode.UIndex; //Uindex incomingSpecEndProp.Value = startNode.UIndex; //Add reachspec to destination node's path list (returning) var DestPathList = destinationNode.GetProperty <ArrayProperty <ObjectProperty> >("PathList"); DestPathList.Add(new ObjectProperty(incomingSpec.UIndex)); destinationNode.WriteProperty(DestPathList); //destNode.WriteProperty(DestPathList); SetReachSpecSize(incomingSpecProperties, size.SpecRadius, size.SpecHeight); incomingSpec.WriteProperties(incomingSpecProperties); } //Reindex reachspecs. SharedPathfinding.ReindexMatchingObjects(outgoingSpec); } } }
public static bool RandomizeBasicGestures(ExportEntry export, RandomizationOption option) { if (!CanRandomize(export)) { return(false); } if (export.GetProperty <ObjectProperty>("SkeletalMeshComponent")?.ResolveToEntry(export.FileRef) is ExportEntry smc) { //Debug.WriteLine($"Installing new lite animations for {export.InstancedFullPath}"); var animsets = smc.GetProperty <ArrayProperty <ObjectProperty> >("AnimSets"); var animTreeTemplate = smc.GetProperty <ObjectProperty>("AnimTreeTemplate")?.ResolveToEntry(export.FileRef) as ExportEntry; if (animsets != null && animTreeTemplate != null) { int numAnimationsSupported = 0; foreach (var animsetO in animsets) { var animset = animsetO.ResolveToEntry(export.FileRef) as ExportEntry; var sequences = animset.GetProperty <ArrayProperty <ObjectProperty> >("Sequences"); numAnimationsSupported += sequences.Count; } smc.RemoveProperty("AnimSets"); // We want to force new animations. we'll waste a bit of memory doing this but oh well List <RBioEvtSysTrackGesture.Gesture> installedGestures = new List <RBioEvtSysTrackGesture.Gesture>(); var animationPackagesCache = new MERPackageCache(); while (numAnimationsSupported > 0) { // should we make sure they're unique? var randGest = RBioEvtSysTrackGesture.InstallRandomFilteredGestureAsset(export.FileRef, 2, smaKeywords, null, null, true); InstallDynamicAnimSetRefForSkeletalMesh(smc, randGest); installedGestures.Add(randGest); numAnimationsSupported--; } animationPackagesCache.ReleasePackages(); var isSubfile = PackageTools.IsLevelSubfile(Path.GetFileName(export.FileRef.FilePath)); if (isSubfile) { var newName = export.ObjectName + "_MER"; export.ObjectName = new NameReference(newName, ThreadSafeRandom.Next(25685462)); } // Update the anim tree to use the new animations // Too lazy to properly trace to find nodes. Just take children of this node that are AnimNodeSequences // Add blend times to nodes so they 'blend' together a bit more, look a bit less jank SetupChildrenBlend(animTreeTemplate); // If the animtree has 'DebugPostLoad' flag, it means MER already is using this for something else // We need to generate a new tree so the animations work properly if (animTreeTemplate.ObjectFlags.Has(UnrealFlags.EObjectFlags.DebugPostLoad)) { animTreeTemplate = EntryCloner.CloneTree(animTreeTemplate, true); animTreeTemplate.ObjectName = export.FileRef.GetNextIndexedName("MER_AnimTree"); // New name smc.WriteProperty(new ObjectProperty(animTreeTemplate, "AnimTreeTemplate")); // Write the template back } else if (isSubfile) { // if it's a subfile it won't be used as an import // Let's rename this object animTreeTemplate.ObjectName = new NameReference("MER_AnimTree", ThreadSafeRandom.Next(200000000)); // New name } var animNodeSequences = export.FileRef.Exports.Where(x => x.idxLink == animTreeTemplate.UIndex && x.IsA("AnimNodeSequence")).ToList(); for (int i = 0; i < installedGestures.Count; i++) { var installedG = installedGestures[i]; var ans = animNodeSequences[i]; ans.WriteProperty(new NameProperty(installedG.GestureAnim, "AnimSeqName")); } animTreeTemplate.ObjectFlags |= UnrealFlags.EObjectFlags.DebugPostLoad; // Set as used return(true); } } return(false); }
/// <summary> /// Gets the end name of a ReachSpec for property parsing. ME1 uses Nav, while ME2 and above use Actor. /// </summary> /// <param name="export">export used to determine which game is being parsed</param> /// <returns>Actor for ME2/ME3, Nav for ME1</returns> public static string GetReachSpecEndName(ExportEntry export) => export.FileRef.Game < MEGame.ME3 && export.FileRef.Platform != MEPackage.GamePlatform.PS3 ? "Nav" : "Actor";
/// <summary> /// UDKFile class constructor. It also load namelist, importlist and exportinfo (not exportdata) from udk file /// </summary> /// <param name="udkFilePath">full path + file name of desired udk file.</param> public UDKFile(string udkFilePath, bool fullFileInMemory = false) { Loaded = true; FileName = Path.GetFullPath(udkFilePath); using (FileStream udkStream = File.OpenRead(FileName)) { Names = new List<NameEntry>(); Imports = new List<ImportEntry>(); Exports = new List<ExportEntry>(); udkStream.Read(header, 0, header.Length); //unsure about magic number. for now just let it try anything if (magic != 2653586369) { //throw new FormatException("not a udk file"); } //again, unsure of what versions ought to be supported if (lowVers != 684 && highVers != 0) { //throw new FormatException("unsupported version"); } Stream listsStream; listsStream = udkStream; headerEnd = NameOffset; // fill names list listsStream.Seek(NameOffset, SeekOrigin.Begin); for (int i = 0; i < NameCount; i++) { long currOffset = listsStream.Position; int strLength = listsStream.ReadValueS32(); NameEntry n = new NameEntry(); if (strLength < 0) { n.name = listsStream.ReadString(strLength * -2, true, Encoding.Unicode); } else { n.name = listsStream.ReadString(strLength, true, Encoding.ASCII); } n.unk = listsStream.ReadValueS32(); n.flags = listsStream.ReadValueS32(); Names.Add(n); } //Debug.WriteLine("Names done. Current offset: "+listsStream.Position); //Debug.WriteLine("Import Offset: " + ImportOffset); // fill import list //Console.Out.WriteLine("IMPORT OFFSET: " + ImportOffset); listsStream.Seek(ImportOffset, SeekOrigin.Begin); byte[] buffer = new byte[ImportEntry.byteSize]; for (int i = 0; i < ImportCount; i++) { long offset = listsStream.Position; ImportEntry e = new ImportEntry(this, listsStream); Imports.Add(e); //Debug.WriteLine("Read import " + i + " " + e.ObjectName + ", offset: " + offset); }; // fill export list (only the headers, not the data) listsStream.Seek(ExportOffset, SeekOrigin.Begin); //Console.Out.WriteLine("Export OFFSET: " + ImportOffset); for (int i = 0; i < ExportCount; i++) { uint expInfoOffset = (uint)listsStream.Position; listsStream.Seek(44, SeekOrigin.Current); int count = listsStream.ReadValueS32(); listsStream.Seek(-48, SeekOrigin.Current); int expInfoSize = 68 + (count * 4); buffer = new byte[expInfoSize]; listsStream.Read(buffer, 0, buffer.Length); ExportEntry e = new ExportEntry(this, buffer, expInfoOffset); //Debug.WriteLine("Read export " + i + " " + e.ObjectName + ", offset: " + expInfoOffset+ ", size: "+expInfoSize); Exports.Add(e); } } Debug.WriteLine(getMetadataString()); }
public static void SetCollectionActorLocation(ExportEntry component, float x, float y, float z, List <ExportEntry> collectionitems = null, ExportEntry collectionactor = null) { if (collectionactor == null) { if (!(component.HasParent && component.Parent.ClassName.Contains("CollectionActor"))) { return; } collectionactor = (ExportEntry)component.Parent; } collectionitems ??= GetCollectionItems(collectionactor); if (collectionitems?.Count > 0) { var idx = collectionitems.FindIndex(o => o != null && o.UIndex == component.UIndex); if (idx >= 0) { var binData = (StaticCollectionActor)ObjectBinary.From(collectionactor); Matrix m = binData.LocalToWorldTransforms[idx]; m.TranslationVector = new Vector3(x, y, z); binData.LocalToWorldTransforms[idx] = m; collectionactor.WriteBinary(binData); } } }
public void addExport(ExportEntry exportEntry) { if (exportEntry.udkRef != this) throw new Exception("you cannot add a new export entry from another udk file, it has invalid references!"); exportEntry.hasChanged = true; //changing data offset in order to append it at the end of the file int maxOffset = Exports.Max(entry => entry.DataOffset); ExportEntry lastExport = Exports.Find(export => export.DataOffset == maxOffset); int lastOffset = lastExport.DataOffset + lastExport.Data.Length; exportEntry.DataOffset = lastOffset; Exports.Add(exportEntry); ExportCount = Exports.Count; }
private bool CanRandomize(ExportEntry export) => export.ClassName == @"BioWaypointSet";
private void ReadMaterial(ExportEntry export, PackageCache assetCache = null) { if (export.ClassName == "Material") { var parsedMaterial = ObjectBinary.From <Material>(export); StaticParameterSet = (StaticParameterSet)parsedMaterial.SM3MaterialResource.ID; foreach (var v in parsedMaterial.SM3MaterialResource.UniformExpressionTextures) { IEntry tex = export.FileRef.GetEntry(v.value); if (tex != null) { Textures.Add(tex); } } } else if (export.ClassName == "RvrEffectsMaterialUser") { var props = export.GetProperties(); if (export.GetProperty <ObjectProperty>("m_pBaseMaterial") is ObjectProperty baseProp) { // This is an instance... maybe? if (baseProp.Value > 0) { // Local export ReadMaterial(export.FileRef.GetUExport(baseProp.Value)); } else { ImportEntry ie = export.FileRef.GetImport(baseProp.Value); var externalEntry = EntryImporter.ResolveImport(ie, null, assetCache); if (externalEntry != null) { ReadMaterial(externalEntry); } } } } else if (export.ClassName == "MaterialInstanceConstant") { if (ObjectBinary.From(export) is MaterialInstance matInstBin) { StaticParameterSet = matInstBin.SM3StaticParameterSet; } //Read Local if (export.GetProperty <ArrayProperty <StructProperty> >("TextureParameterValues") is ArrayProperty <StructProperty> textureparams) { foreach (var param in textureparams) { var paramValue = param.GetProp <ObjectProperty>("ParameterValue"); var texntry = export.FileRef.GetEntry(paramValue.Value); if (texntry?.ClassName == "Texture2D" && !Textures.Contains(texntry)) { Textures.Add(texntry); } } } if (export.GetProperty <ArrayProperty <ObjectProperty> >("ReferencedTextures") is ArrayProperty <ObjectProperty> textures) { foreach (var obj in textures) { var texntry = export.FileRef.GetEntry(obj.Value); if (texntry.ClassName == "Texture2D" && !Textures.Contains(texntry)) { Textures.Add(texntry); } } } //Read parent if (export.GetProperty <ObjectProperty>("Parent") is ObjectProperty parentObjProp) { // This is an instance... maybe? if (parentObjProp.Value > 0) { // Local export ReadMaterial(export.FileRef.GetUExport(parentObjProp.Value)); } else { ImportEntry ie = export.FileRef.GetImport(parentObjProp.Value); var externalEntry = ModelPreview.FindExternalAsset(ie, null, null); if (externalEntry != null) { ReadMaterial(externalEntry); } } } } }
private static bool CanRandomize(ExportEntry export, out int shiftDirection, out float min, out float max) { min = -7; max = 7; shiftDirection = -1; if (export.IsDefaultObject || export.ClassName != "MorphTarget") { return(false); } // Check and setup shift directions. var name = export.ObjectName.Name; if (name.Contains("eye")) { shiftDirection = SetupShiftDir("eye"); min = -1; max = 5; return(true); } if (name.Contains("jaw")) { shiftDirection = SetupShiftDir("jaw"); if (shiftDirection == 0) { // in/out min = -5f; max = 20; } else { // up down left right min = -1f; max = 20f; } return(true); } if (name.Contains("mouth")) { shiftDirection = SetupShiftDir("mouth"); if (shiftDirection == 0) { // in/out min = -5f; max = 20; } else { // up down left right min = -5f; max = 5f; } return(true); } if (name.Contains("nose")) { shiftDirection = SetupShiftDir("nose"); if (shiftDirection == 0) { // in/out min = -15f; max = 15; } else { // up down min = -2f; max = 10f; } return(true); } // Leave disabled. Doesn't seem to do anything useful //if (name.Contains("teeth")) //{ // shiftDirection = SetupShiftDir("teeth"); // min = -5; // max = 5; // return true; //} Debug.WriteLine($"Ignored thing {name}"); return(false); }
public bool SaveToFile(bool forceZlib = false) { if (forceZlib && compressionType != CompressionType.Zlib) { modified = true; } if (packageFile.Length == 0 || !modified) { return(false); } MemoryStream tempOutput = new MemoryStream(); List <ExportEntry> sortedExports = exportsTable.OrderBy(s => s.dataOffset).ToList(); if (!compressed) { packageFile.SeekBegin(); tempOutput.WriteFromStream(packageFile, sortedExports[0].dataOffset); } else { packageData.SeekBegin(); tempOutput.WriteFromStream(packageData, packageData.Length); } for (int i = 0; i < exportsCount; i++) { ExportEntry export = sortedExports[i]; uint dataLeft; tempOutput.JumpTo(export.dataOffset); if (i + 1 == exportsCount) { dataLeft = exportsEndOffset - export.dataOffset - export.dataSize; } else { dataLeft = sortedExports[i + 1].dataOffset - export.dataOffset - export.dataSize; } if (export.updatedData) { string exportFile = packagePath + "-exports\\exportId-" + export.id; using (FileStream fs = new FileStream(exportFile, FileMode.Open, FileAccess.Read)) { tempOutput.WriteFromStream(fs, fs.Length); } export.updatedData = false; } else if (export.newData != null) { tempOutput.WriteFromBuffer(export.newData); } else { getData(export.dataOffset, export.dataSize, tempOutput); } tempOutput.WriteZeros(dataLeft); } if (exportsOffset > sortedExports[0].dataOffset) { if (compressed) // allowed only uncompressed { throw new Exception(); } exportsOffset = (uint)tempOutput.Position; saveExports(tempOutput); exportsEndOffset = (uint)tempOutput.Position; } else { tempOutput.JumpTo(exportsOffset); saveExports(tempOutput); } tempOutput.JumpTo(exportsEndOffset); if (namesOffset > sortedExports[0].dataOffset) { if (compressed) // allowed only uncompressed { throw new Exception(); } namesOffset = (uint)tempOutput.Position; saveNames(tempOutput, true); } else { saveNames(tempOutput); } if (importsOffset > sortedExports[0].dataOffset) { if (compressed) // allowed only uncompressed { throw new Exception(); } importsOffset = (uint)tempOutput.Position; saveImports(tempOutput, true); } else { saveImports(tempOutput); } if (namesOffset > sortedExports[0].dataOffset || importsOffset > sortedExports[0].dataOffset || exportsOffset > sortedExports[0].dataOffset) { tempOutput.SeekBegin(); tempOutput.Write(packageHeader, 0, packageHeader.Length); } packageFile.Close(); if (!memoryMode && Directory.Exists(packagePath + "-exports")) { Directory.Delete(packagePath + "-exports", true); } string filename = packageFile.Name; using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write)) { if (fs == null) { throw new Exception("Failed to write to file: " + filename); } if (!compressed) { tempOutput.SeekBegin(); fs.WriteFromStream(tempOutput, tempOutput.Length); } else { if (chunks == null) { chunks = new List <Chunk>(); } chunks.Clear(); Chunk chunk = new Chunk(); chunk.uncomprSize = sortedExports[0].dataOffset - (uint)dataOffset; chunk.uncomprOffset = (uint)dataOffset; for (int i = 0; i < exportsCount; i++) { ExportEntry export = sortedExports[i]; uint dataSize; if (i + 1 == exportsCount) { dataSize = exportsEndOffset - export.dataOffset; } else { dataSize = sortedExports[i + 1].dataOffset - export.dataOffset; } if (chunk.uncomprSize + dataSize > maxChunkSize) { uint offset = chunk.uncomprOffset + chunk.uncomprSize; chunks.Add(chunk); chunk = new Chunk(); chunk.uncomprSize = dataSize; chunk.uncomprOffset = offset; } else { chunk.uncomprSize += dataSize; } } chunks.Add(chunk); if (forceZlib) { compressionType = CompressionType.Zlib; // override compression type to Zlib } fs.Write(packageHeader, 0, packageHeader.Length); fs.WriteUInt32((uint)compressionType); fs.WriteUInt32((uint)chunks.Count); uint chunksTableOffset = (uint)fs.Position; fs.Skip(SizeOfChunk * chunks.Count); // skip chunks table - filled later fs.WriteUInt32(someTag); if (version == packageFileVersionME2) { fs.WriteUInt32(0); // const 0 } saveExtraNames(fs); for (int c = 0; c < chunks.Count; c++) { chunk = chunks[c]; chunk.comprOffset = (uint)fs.Position; chunk.comprSize = 0; // filled later uint dataBlockLeft = chunk.uncomprSize; uint newNumBlocks = (chunk.uncomprSize + maxBlockSize - 1) / maxBlockSize; // skip blocks header and table - filled later fs.Seek(SizeOfChunk + SizeOfChunkBlock * newNumBlocks, SeekOrigin.Current); tempOutput.JumpTo(chunk.uncomprOffset); chunk.blocks = new List <ChunkBlock>(); for (int b = 0; b < newNumBlocks; b++) { ChunkBlock block = new ChunkBlock(); block.uncomprSize = Math.Min(maxBlockSize, dataBlockLeft); dataBlockLeft -= block.uncomprSize; block.uncompressedBuffer = tempOutput.ReadToBuffer(block.uncomprSize); chunk.blocks.Add(block); } if (compressionType == CompressionType.LZO) { for (int b = 0; b < newNumBlocks; b++) { ChunkBlock block = chunk.blocks[b]; block.compressedBuffer = LZO2Helper.LZO2.Compress(block.uncompressedBuffer); if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; chunk.blocks[b] = block; } } else { Parallel.For(0, chunk.blocks.Count, b => { ChunkBlock block = chunk.blocks[b]; if (compressionType == CompressionType.Zlib) { block.compressedBuffer = ZlibHelper.Zlib.Compress(block.uncompressedBuffer); } else { throw new Exception("Compression type not expected!"); } if (block.compressedBuffer.Length == 0) { throw new Exception("Compression failed!"); } block.comprSize = (uint)block.compressedBuffer.Length; chunk.blocks[b] = block; }); } for (int b = 0; b < newNumBlocks; b++) { ChunkBlock block = chunk.blocks[b]; fs.Write(block.compressedBuffer, 0, (int)block.comprSize); chunk.comprSize += block.comprSize; } chunks[c] = chunk; } for (int c = 0; c < chunks.Count; c++) { chunk = chunks[c]; fs.JumpTo(chunksTableOffset + c * SizeOfChunk); // jump to chunks table fs.WriteUInt32(chunk.uncomprOffset); fs.WriteUInt32(chunk.uncomprSize); fs.WriteUInt32(chunk.comprOffset); fs.WriteUInt32(chunk.comprSize + SizeOfChunk + SizeOfChunkBlock * (uint)chunk.blocks.Count); fs.JumpTo(chunk.comprOffset); // jump to blocks header fs.WriteUInt32(packageTag); fs.WriteUInt32(maxBlockSize); fs.WriteUInt32(chunk.comprSize); fs.WriteUInt32(chunk.uncomprSize); foreach (ChunkBlock block in chunk.blocks) { fs.WriteUInt32(block.comprSize); fs.WriteUInt32(block.uncomprSize); } } for (int c = 0; c < chunks.Count; c++) { chunk = chunks[c]; chunk.blocks.Clear(); chunk.blocks = null; } chunks.Clear(); chunks = null; } } tempOutput.Close(); tempOutput.Dispose(); return(true); }
public static void ReadExports() { int pos = header.ExportOffset; exportlist = new List<ExportEntry>(); int unkc; for (int i = 0; i < header.ExportCount; i++) { ExportEntry e = new ExportEntry(); e.Class = GetInt(pos); e.Link = GetInt(pos + 8); e.Name = GetInt(pos + 12); e.DataSize = GetInt(pos + 36); e.DataOffset = GetInt(pos + 40); e.Offset = pos; unkc = GetInt(pos + 44); pos += 0x44 + unkc * 12; exportlist.Add(e); } }
private void ReadExports(FileStream fs) { fs.Seek(ExportOffset, SeekOrigin.Begin); int pos = ExportOffset; Exports = new List<ExportEntry>(); for (int i = 0; i < ExportCount; i++) { int start = pos; int clas = ReadInt32(fs, pos); pos += 8; int link = ReadInt32(fs, pos); pos += 4; int name = ReadInt32(fs, pos); pos += 16; int flags = ReadInt32(fs, pos); pos += 4; int size = ReadInt32(fs, pos); pos += 4; int offset = ReadInt32(fs, pos); pos += 8; int count = ReadInt32(fs, pos); pos += 24 + count * 4; int len = pos - start; byte[] buff = new byte[len]; fs.Seek(start, SeekOrigin.Begin); for (int j = 0; j < len; j++) buff[j] = (byte)fs.ReadByte(); byte[] buff2 = new byte[size]; fs.Seek(offset, SeekOrigin.Begin); for (int j = 0; j < size; j++) buff2[j] = (byte)fs.ReadByte(); byte[] buff3 = new byte[size]; for (int j = 0; j < size; j++) buff3[j] = buff2[j]; ExportEntry e = new ExportEntry(); e.clas = clas; e.link = link; e.name = name; e.flags = flags; e.size = size; e.offset = offset; e.raw = buff; e.data = buff2; e.olddata = buff3; e.IsChanged = false; Exports.Add(e); } }
public static void CreateOutputLink(ExportEntry source, string outLinkDescription, ExportEntry destExport, int inputIndex = 0) { if (source.GetProperty <ArrayProperty <StructProperty> >("OutputLinks") is { } outLinksProp) { foreach (var prop in outLinksProp) { if (prop.GetProp <StrProperty>("LinkDesc") == outLinkDescription) { var linksProp = prop.GetProp <ArrayProperty <StructProperty> >("Links"); linksProp.Add(new StructProperty("SeqOpOutputInputLink", false, new ObjectProperty(destExport, "LinkedOp"), new IntProperty(inputIndex, "InputLinkIdx"))); source.WriteProperty(outLinksProp); return; } } } }
public static void CreateVariableLink(ExportEntry src, string linkDescription, ExportEntry dest) { if (src.GetProperty <ArrayProperty <StructProperty> >("VariableLinks") is { } varLinksProp) { foreach (var prop in varLinksProp) { if (prop.GetProp <StrProperty>("LinkDesc") == linkDescription) { prop.GetProp <ArrayProperty <ObjectProperty> >("LinkedVariables").Add(new ObjectProperty(dest)); src.WriteProperty(varLinksProp); } } } }
private void ReadExportTable() { try { DebugLog.PrintLn("Reading Export Table..."); Exports = new List<ExportEntry>(); if (GeneralInfo.compressed) { UncompressRange(Header._offsetCompFlagEnd + 0xC, Header.HeaderLength - (Header._offsetCompFlagEnd + 0xC)); Header.DeCompBuffer.Seek(Header.ExportOffset, 0); for (int i = 0; i < Header.ExportCount; i++) { ExportEntry e = new ExportEntry(); e.idxClass = ReadInt(Header.DeCompBuffer); e.idxParent = ReadInt(Header.DeCompBuffer); e.idxLink = ReadInt(Header.DeCompBuffer); e.idxName = ReadInt(Header.DeCompBuffer); e.Index = ReadInt(Header.DeCompBuffer); e.idxArchetype = ReadInt(Header.DeCompBuffer); e.Unk1 = ReadInt(Header.DeCompBuffer); e.ObjectFlags = ReadInt(Header.DeCompBuffer); e.Datasize = ReadInt(Header.DeCompBuffer); e.Dataoffset = ReadInt(Header.DeCompBuffer); long pos = Header.DeCompBuffer.Position; if (!GeneralInfo.loadfull) e.DataLoaded = false; else { e.Data = GetObjectData(e.Dataoffset, e.Datasize); e.DataLoaded = true; } Header.DeCompBuffer.Seek(pos, 0); e.Unk2 = ReadInt(Header.DeCompBuffer); int count = ReadInt(Header.DeCompBuffer); e.Unk3 = new int[count]; for (int j = 0; j < count; j++) e.Unk3[j] = ReadInt(Header.DeCompBuffer); e.Unk4 = ReadInt(Header.DeCompBuffer); e.Unk5 = ReadInt(Header.DeCompBuffer); e.Unk6 = ReadInt(Header.DeCompBuffer); e.Unk7 = ReadInt(Header.DeCompBuffer); e.Unk8 = ReadInt(Header.DeCompBuffer); Exports.Add(e); } } else { Source.Seek(Header.ExportOffset, 0); for (int i = 0; i < Header.ExportCount; i++) { ExportEntry e = new ExportEntry(); e.idxClass = ReadInt(Source); e.idxParent = ReadInt(Source); e.idxLink = ReadInt(Source); e.idxName = ReadInt(Source); e.Index = ReadInt(Source); e.idxArchetype = ReadInt(Source); e.Unk1 = ReadInt(Source); e.ObjectFlags = ReadInt(Source); e.Datasize = ReadInt(Source); e.Dataoffset = ReadInt(Source); long pos = Source.Position; if (!GeneralInfo.loadfull) e.DataLoaded = false; else { e.Data = GetObjectData(e.Dataoffset, e.Datasize); e.DataLoaded = true; } Source.Seek(pos, 0); e.Unk2 = ReadInt(Source); int count = ReadInt(Source); e.Unk3 = new int[count]; for (int j = 0; j < count; j++) e.Unk3[j] = ReadInt(Source); e.Unk4 = ReadInt(Source); e.Unk5 = ReadInt(Source); e.Unk6 = ReadInt(Source); e.Unk7 = ReadInt(Source); e.Unk8 = ReadInt(Source); Exports.Add(e); } } DebugLog.PrintLn("Done."); } catch (Exception ex) { DebugLog.PrintLn("PCCPACKAGE::READEXPORTTABLE ERROR:\n" + ex.Message); } }