public static void WritePropHeader(this Stream stream, IMEPackage pcc, string propName, PropertyType type, int size)
 {
     stream.WriteValueS32(pcc.FindNameOrAdd(propName));
     stream.WriteValueS32(0);
     stream.WriteValueS32(pcc.FindNameOrAdd(type.ToString()));
     stream.WriteValueS32(0);
     stream.WriteValueS32(size);
     stream.WriteValueS32(0);
 }
Example #2
0
        /// <summary>
        /// Trashes an entry.
        /// </summary>
        /// <param name="entry">Entry to trash</param>
        /// <param name="trashContainer">Container for trash. Pass null if you want to create the trash container from the passed in value.</param>
        /// <param name="packageClassIdx">Idx for package class. Prevents multiple calls to find it</param>
        /// <returns>New trash container, otherwise will be null</returns>
        public static ExportEntry TrashEntry(IEntry entry, ExportEntry trashContainer, int packageClassIdx)
        {
            IMEPackage pcc = entry.FileRef;

            if (entry is ImportEntry imp)
            {
                if (trashContainer == null)
                {
                    trashContainer = TrashEntry(new ExportEntry(pcc), null, packageClassIdx);
                    pcc.addExport(trashContainer);
                    trashContainer.indexValue = 0;
                }
                imp.idxClassName   = pcc.FindNameOrAdd("Package");
                imp.idxPackageFile = pcc.FindNameOrAdd("Core");
                imp.idxLink        = trashContainer.UIndex;
                imp.idxObjectName  = pcc.FindNameOrAdd("Trash");
                imp.indexValue     = 0;
            }
            else if (entry is ExportEntry exp)
            {
                MemoryStream trashData = new MemoryStream();
                trashData.WriteInt32(-1);
                trashData.WriteInt32(pcc.findName("None"));
                trashData.WriteInt32(0);
                exp.Data          = trashData.ToArray();
                exp.idxArchtype   = 0;
                exp.idxSuperClass = 0;
                exp.indexValue    = 0;
                exp.idxClass      = packageClassIdx;
                exp.ObjectFlags  &= ~UnrealFlags.EObjectFlags.HasStack;
                if (trashContainer == null)
                {
                    exp.idxObjectName = pcc.FindNameOrAdd(UnrealPackageFile.TrashPackageName);
                    exp.idxLink       = 0;
                    if (exp.idxLink == exp.UIndex)
                    {
                        Debugger.Break();
                    }
                    exp.PackageGUID = UnrealPackageFile.TrashPackageGuid;
                    trashContainer  = exp;
                }
                else
                {
                    exp.idxLink = trashContainer.UIndex;
                    if (exp.idxLink == exp.UIndex)
                    {
                        //This should not occur
                        Debugger.Break();
                    }
                    exp.idxObjectName = pcc.FindNameOrAdd("Trash");
                    exp.PackageGUID   = Guid.Empty;
                }
            }
            return(trashContainer);
        }
 public static void WriteEnumProperty(this Stream stream, IMEPackage pcc, string propName, NameReference enumName, NameReference enumValue)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 8);
     if (pcc.Game == MEGame.ME3)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd(enumName.Name));
         stream.WriteValueS32(enumName.Number);
     }
     stream.WriteValueS32(pcc.FindNameOrAdd(enumValue.Name));
     stream.WriteValueS32(enumValue.Number);
 }
 public static void WriteEnumProperty(this Stream stream, IMEPackage pcc, string propName, string enumName, string enumValue, int index = 0)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 8);
     if (pcc.Game == MEGame.ME3)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd(enumName));
         stream.WriteValueS32(0);
     }
     stream.WriteValueS32(pcc.FindNameOrAdd(enumValue));
     stream.WriteValueS32(index);
 }
Example #5
0
 public override void WriteTo(Stream stream, IMEPackage pcc, bool valueOnly = false)
 {
     if (!valueOnly)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd(Name));
         stream.WriteValueS32(0);
         stream.WriteValueS32(pcc.FindNameOrAdd(TypeName));
         stream.WriteValueS32(0);
         stream.WriteValueS32(raw.Length);
         stream.WriteValueS32(0);
     }
     stream.WriteBytes(raw);
 }
 public static void WriteStructProperty(this Stream stream, IMEPackage pcc, string propName, string structName, MemoryStream value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.StructProperty, (int)value.Length);
     stream.WriteValueS32(pcc.FindNameOrAdd(structName));
     stream.WriteValueS32(0);
     stream.WriteStream(value);
 }
 public static void WriteDelegateProperty(this Stream stream, IMEPackage pcc, string propName, ScriptDelegate value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.DelegateProperty, 12);
     stream.WriteInt32(value.Object);
     stream.WriteInt32(pcc.FindNameOrAdd(value.FunctionName.Name));
     stream.WriteInt32(value.FunctionName.Number);
 }
        public static void WriteNoneProperty(this Stream stream, IMEPackage pcc)
        {
            //Debug.WriteLine("Writing none property at 0x" + stream.Position.ToString("X6"));

            stream.WriteValueS32(pcc.FindNameOrAdd("None"));
            stream.WriteValueS32(0);
        }
 public static void WriteDelegateProperty(this Stream stream, IMEPackage pcc, string propName, int unk, NameReference value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.DelegateProperty, 12);
     stream.WriteValueS32(unk);
     stream.WriteValueS32(pcc.FindNameOrAdd(value.Name));
     stream.WriteValueS32(value.Number);
 }
        public static void WriteNameProperty(this Stream stream, IMEPackage pcc, string propName, NameReference value)
        {
            //Debug.WriteLine("Writing name property " + propName + ", value: " + value + " at 0x" + stream.Position.ToString("X6"));

            stream.WritePropHeader(pcc, propName, PropertyType.NameProperty, 8);
            stream.WriteValueS32(pcc.FindNameOrAdd(value.Name));
            stream.WriteValueS32(value.Number);
        }
Example #11
0
        /// <summary>
        /// Trashes an entry.
        /// </summary>
        /// <param name="entry">Entry to trash</param>
        /// <param name="trashContainer">Container for trash. Pass null if you want to create the trash container from the passed in value.</param>
        /// <param name="packageClass">Package class. Prevents multiple calls to find it</param>
        /// <returns>New trash container, otherwise will be null</returns>
        private static ExportEntry TrashEntry(IEntry entry, ExportEntry trashContainer, IEntry packageClass)
        {
            IMEPackage pcc = entry.FileRef;

            if (entry is ImportEntry imp)
            {
                if (trashContainer == null)
                {
                    trashContainer = TrashEntry(new ExportEntry(pcc), null, packageClass);
                    pcc.AddExport(trashContainer);
                    trashContainer.indexValue = 0;
                }
                imp.ClassName   = "Package";
                imp.PackageFile = "Core";
                imp.idxLink     = trashContainer.UIndex;
                imp.ObjectName  = "Trash";
                imp.indexValue  = 0;
            }
            else if (entry is ExportEntry exp)
            {
                MemoryStream trashData = new MemoryStream();
                trashData.WriteInt32(-1);
                trashData.WriteInt32(pcc.FindNameOrAdd("None"));
                trashData.WriteInt32(0);
                exp.Data         = trashData.ToArray();
                exp.Archetype    = null;
                exp.SuperClass   = null;
                exp.indexValue   = 0;
                exp.Class        = packageClass;
                exp.ObjectFlags &= ~UnrealFlags.EObjectFlags.HasStack;
                exp.ObjectFlags &= ~UnrealFlags.EObjectFlags.ArchetypeObject;
                exp.ObjectFlags &= ~UnrealFlags.EObjectFlags.ClassDefaultObject;
                if (trashContainer == null)
                {
                    exp.ObjectName = UnrealPackageFile.TrashPackageName;
                    exp.idxLink    = 0;
                    if (exp.idxLink == exp.UIndex)
                    {
                        Debugger.Break();
                    }
                    exp.PackageGUID = UnrealPackageFile.TrashPackageGuid;
                    trashContainer  = exp;
                }
                else
                {
                    exp.idxLink = trashContainer.UIndex;
                    if (exp.idxLink == exp.UIndex)
                    {
                        //This should not occur
                        Debugger.Break();
                    }
                    exp.ObjectName  = "Trash";
                    exp.PackageGUID = Guid.Empty;
                }
            }
            return(trashContainer);
        }
        public static void WriteStructProperty(this Stream stream, IMEPackage pcc, string propName, string structName, MemoryStream value)
        {
            //Debug.WriteLine("Writing struct property " + propName + ", value: " + value + " at 0x" + stream.Position.ToString("X6"));

            stream.WritePropHeader(pcc, propName, PropertyType.StructProperty, (int)value.Length);
            stream.WriteValueS32(pcc.FindNameOrAdd(structName));
            stream.WriteValueS32(0);
            stream.WriteStream(value);
        }
 public static void WriteByteProperty(this Stream stream, IMEPackage pcc, string propName, byte value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 1);
     if (pcc.Game == MEGame.ME3)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd("None"));
         stream.WriteValueS32(0);
     }
     stream.WriteByte(value);
 }
 public static void WriteByteProperty(this Stream stream, IMEPackage pcc, string propName, byte value)
 {
     //Debug.WriteLine("Writing byte property " + propName + ", value: " + value + " at 0x" + stream.Position.ToString("X6"));
     stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 1);
     if (pcc.Game == MEGame.ME3)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd("None"));
         stream.WriteValueS32(0);
     }
     stream.WriteByte(value);
 }
Example #15
0
 public override void WriteTo(Stream stream, IMEPackage pcc, bool valueOnly = false)
 {
     if (!valueOnly)
     {
         stream.WriteNameProperty(pcc, Name, Value);
     }
     else
     {
         stream.WriteValueS32(pcc.FindNameOrAdd(Value.Name));
         stream.WriteValueS32(Value.Number);
     }
 }
Example #16
0
        //if neccessary, will fill in parents as Package Imports (if the import you need has non-Package parents, don't use this method)
        public static IEntry getEntryOrAddImport(this IMEPackage pcc, string fullPath, string className = "Class", string packageFile = "Core")
        {
            if (string.IsNullOrEmpty(fullPath))
            {
                return(null);
            }

            //see if this import exists locally
            foreach (ImportEntry imp in pcc.Imports)
            {
                if (imp.GetFullPath == fullPath)
                {
                    return(imp);
                }
            }

            //see if this is an export and exists locally
            foreach (ExportEntry exp in pcc.Exports)
            {
                if (exp.GetFullPath == fullPath)
                {
                    return(exp);
                }
            }

            string[] pathParts = fullPath.Split('.');

            IEntry parent = pcc.getEntryOrAddImport(string.Join(".", pathParts.Take(pathParts.Length - 1)), "Package");

            var import = new ImportEntry(pcc)
            {
                idxLink        = parent?.UIndex ?? 0,
                idxClassName   = pcc.FindNameOrAdd(className),
                idxObjectName  = pcc.FindNameOrAdd(pathParts.Last()),
                idxPackageFile = pcc.FindNameOrAdd(packageFile)
            };

            pcc.addImport(import);
            return(import);
        }
 public override void WriteTo(Stream stream, IMEPackage pcc, bool valueOnly = false)
 {
     if (!valueOnly)
     {
         stream.WriteDelegateProperty(pcc, Name, unk, Value);
     }
     else
     {
         stream.WriteValueS32(unk);
         stream.WriteValueS32(pcc.FindNameOrAdd(Value.Name));
         stream.WriteValueS32(Value.count);
     }
 }
Example #18
0
        public static void TrashEntries(IMEPackage pcc, IEnumerable <IEntry> itemsToTrash)
        {
            ExportEntry trashTopLevel = pcc.Exports.FirstOrDefault(x => x.idxLink == 0 && x.ObjectName == UnrealPackageFile.TrashPackageName);
            ImportEntry packageImport = pcc.Imports.FirstOrDefault(x => x.GetFullPath == "Core.Package");

            if (packageImport == null)
            {
                ImportEntry coreImport = pcc.Imports.FirstOrDefault(x => x.GetFullPath == "Core");
                if (coreImport == null)
                {
                    //really small file
                    coreImport = new ImportEntry(pcc)
                    {
                        idxObjectName  = pcc.FindNameOrAdd("Core"),
                        idxClassName   = pcc.FindNameOrAdd("Package"),
                        idxLink        = 0,
                        idxPackageFile = pcc.FindNameOrAdd("Core")
                    };
                    pcc.addImport(coreImport);
                }

                //Package isn't an import, could be one of the 2DA files or other small ones
                packageImport = new ImportEntry(pcc)
                {
                    idxObjectName  = pcc.FindNameOrAdd("Package"),
                    idxClassName   = pcc.FindNameOrAdd("Class"),
                    idxLink        = coreImport.UIndex,
                    idxPackageFile = pcc.FindNameOrAdd("Core")
                };
                pcc.addImport(packageImport);
            }

            foreach (IEntry entry in itemsToTrash)
            {
                if (entry == trashTopLevel || entry.ObjectName == "Trash") //don't trash what's already been trashed
                {
                    continue;
                }
                trashTopLevel = TrashEntry(entry, trashTopLevel, packageImport.UIndex);
            }
            pcc.RemoveTrailingTrash();
        }
Example #19
0
        /// <summary>
        /// Imports an export from another package file.
        /// </summary>
        /// <param name="mePackage"></param>
        /// <param name="ex">Export object from the other package to import</param>
        /// <param name="link">Local parent node UIndex</param>
        /// <param name="outputEntry">Newly generated export entry reference</param>
        /// <returns></returns>
        private static bool importExport(IMEPackage mePackage, ExportEntry ex, int link, out ExportEntry outputEntry)
        {
            byte[] prePropBinary;
            if (ex.HasStack)
            {
                if (mePackage.Game < MEGame.ME3)
                {
                    prePropBinary = new byte[]
                    {
                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
                    };
                }
                else
                {
                    prePropBinary = new byte[]
                    {
                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
                    };
                }
            }
            else
            {
                int start = ex.GetPropertyStart();
                prePropBinary = new byte[start];
            }

            PropertyCollection props = ex.GetProperties();
            //store copy of names list in case something goes wrong
            List <string> names = mePackage.Names.ToList();

            try
            {
                if (ex.Game != mePackage.Game)
                {
                    props = EntryPruner.RemoveIncompatibleProperties(ex.FileRef, props, ex.ClassName, mePackage.Game);
                }
            }
            catch (Exception exception)
            {
                //restore namelist in event of failure.
                mePackage.setNames(names);
                Console.WriteLine($"Error occured while trying to import {ex.ObjectName} : {exception.Message}");
                //MessageBox.Show($"Error occured while trying to import {ex.ObjectName} : {exception.Message}");
                outputEntry = null;
                return(false);
            }

            //takes care of slight header differences between ME1/2 and ME3
            byte[] newHeader = ex.GenerateHeader(mePackage.Game);

            //for supported classes, this will add any names in binary to the Name table, as well as take care of binary differences for cross-game importing
            //for unsupported classes, this will just copy over the binary
            byte[] binaryData = ExportBinaryConverter.ConvertPostPropBinary(ex, mePackage.Game).ToArray(mePackage);

            int classValue = 0;
            int archetype  = 0;
            int superclass = 0;

            //Set class. This will only work if the class is an import, as we can't reliably pull in exports without lots of other stuff.
            if (ex.idxClass < 0)
            {
                //The class of the export we are importing is an import. We should attempt to relink this.
                ImportEntry portingFromClassImport = ex.FileRef.getImport(ex.idxClass);
                IEntry      newClassImport         = getOrAddCrossImportOrPackage(portingFromClassImport.GetFullPath, ex.FileRef, mePackage);
                classValue = newClassImport.UIndex;
            }
            else if (ex.idxClass > 0)
            {
                //Todo: Add cross mapping support as multi-mode will allow this to work now
                ExportEntry portingInClass = ex.FileRef.getUExport(ex.idxClass);
                ExportEntry matchingExport = mePackage.Exports.FirstOrDefault(x => x.GetIndexedFullPath == portingInClass.GetIndexedFullPath);
                if (matchingExport != null)
                {
                    classValue = matchingExport.UIndex;
                }
            }

            //Set superclass
            if (ex.idxSuperClass < 0)
            {
                //The class of the export we are importing is an import. We should attempt to relink this.
                ImportEntry portingFromClassImport = ex.FileRef.getImport(ex.idxSuperClass);
                IEntry      newClassImport         = getOrAddCrossImportOrPackage(portingFromClassImport.GetFullPath, ex.FileRef, mePackage);
                superclass = newClassImport.UIndex;
            }
            else if (ex.idxSuperClass > 0)
            {
                //Todo: Add cross mapping support as multi-mode will allow this to work now
                ExportEntry portingInClass = ex.FileRef.getUExport(ex.idxSuperClass);
                ExportEntry matchingExport = mePackage.Exports.FirstOrDefault(x => x.GetIndexedFullPath == portingInClass.GetIndexedFullPath);
                if (matchingExport != null)
                {
                    superclass = matchingExport.UIndex;
                }
            }

            //Check archetype.
            if (ex.idxArchtype < 0)
            {
                ImportEntry portingFromClassImport = ex.FileRef.getImport(ex.idxArchtype);
                IEntry      newClassImport         = getOrAddCrossImportOrPackage(portingFromClassImport.GetFullPath, ex.FileRef, mePackage);
                archetype = newClassImport.UIndex;
            }
            else if (ex.idxArchtype > 0)
            {
                ExportEntry portingInClass = ex.FileRef.getUExport(ex.idxArchtype);
                ExportEntry matchingExport = mePackage.Exports.FirstOrDefault(x => x.GetIndexedFullPath == portingInClass.GetIndexedFullPath);
                if (matchingExport != null)
                {
                    archetype = matchingExport.UIndex;
                }
            }

            outputEntry = new ExportEntry(mePackage, prePropBinary, props, binaryData)
            {
                Header        = newHeader,
                idxClass      = classValue,
                idxObjectName = mePackage.FindNameOrAdd(ex.FileRef.getNameEntry(ex.idxObjectName)),
                idxLink       = link,
                idxSuperClass = superclass,
                idxArchtype   = archetype
            };
            mePackage.addExport(outputEntry);

            return(true);
        }
Example #20
0
 public static void WriteNoneProperty(this Stream stream, IMEPackage pcc)
 {
     stream.WriteValueS32(pcc.FindNameOrAdd("None"));
     stream.WriteValueS32(0);
 }
Example #21
0
        public static bool AttemptMerge(IMEPackage vanillaPackage, IMEPackage modifiedVanillaPackage, IMEPackage targetPackage)
        {
            PackageDelta vanillaToModifiedDelta = PackageDelta.CalculateDelta(vanillaPackage, modifiedVanillaPackage);
            PackageDelta vanillaToTargetDelta   = PackageDelta.CalculateDelta(vanillaPackage, targetPackage);
            string       loggingPrefix          = File.Exists(targetPackage.FilePath) ? Path.GetFileName(targetPackage.FilePath) : targetPackage.FilePath;
            //Check merge conditions
            var nameConflicts   = vanillaToModifiedDelta.NameDeltas.Keys.Intersect(vanillaToTargetDelta.NameDeltas.Keys).ToList();
            var importConflicts = vanillaToModifiedDelta.ImportDeltas.Keys.Intersect(vanillaToTargetDelta.ImportDeltas.Keys).ToList();
            var exportConflicts = vanillaToModifiedDelta.ExportDeltas.Keys.Intersect(vanillaToTargetDelta.ExportDeltas.Keys).ToList();

            Log.Information($@"[{loggingPrefix}] Performing three way merge pre-check");
            //Name deltas

            if (nameConflicts.Count > 0)
            {
                //need to check if the conflicts result in same value, in this case it would not be a conflict.
                foreach (int nameIndex in nameConflicts)
                {
                    var modifiedName = modifiedVanillaPackage.Names[nameIndex];
                    var targetName   = targetPackage.Names[nameIndex];
                    if (modifiedName != targetName)
                    {
                        //Differing names in same spots.
                        Log.Information($@"[{loggingPrefix}] Cannot merge files: Name index {nameIndex} is different between modified and target.");
                        return(false);
                    }
                }
            }

            if (importConflicts.Count > 0)
            {
                //todo
            }

            if (exportConflicts.Count > 0)
            {
                //hmm... this will be a tough one.
                foreach (int exportTableIndex in exportConflicts)
                {
                    //we will have to check sizes if we ever hope to have way to merge this
                    var modifiedData = modifiedVanillaPackage.Exports[exportTableIndex].Data;
                    var targetData   = targetPackage.Exports[exportTableIndex].Data;

                    if (!modifiedData.SequenceEqual(targetData))
                    {
                        Log.Information($@"[{loggingPrefix}] Cannot merge files: Export table index {exportTableIndex} data is different between modified and target.");
                        return(false);
                    }

                    //We will have to ignore size here somehow...
                    //var modifiedHeader = modifiedVanillaPackage.Exports[exportTableIndex].Header;
                    //var targetHeader = targetPackage.Exports[exportTableIndex].Header;
                }
            }

            //Merge is OK to perform
            //Apply vanilla to modified delta to target package
            foreach (var nameDelta in vanillaToModifiedDelta.NameDeltas)
            {
                if (nameDelta.Key >= targetPackage.NameCount)
                {
                    //add it
                    Log.Information($@"[{loggingPrefix}] Adding name {nameDelta.Value}");
                    targetPackage.FindNameOrAdd(nameDelta.Value);
                }
                else
                {
                    Log.Information($@"[{loggingPrefix}] Updating name index {nameDelta.Key} to {nameDelta.Value}");
                    targetPackage.replaceName(nameDelta.Key, nameDelta.Value);
                }
            }

            foreach (var exportDelta in vanillaToModifiedDelta.ExportDeltas)
            {
                if (exportDelta.Key >= targetPackage.ExportCount)
                {
                    //add it
                    Log.Information($@"[{loggingPrefix}] Adding export {exportDelta.Value.InstancedFullPath}");
                    targetPackage.AddExport(exportDelta.Value); //not sure if this is possible
                }
                else
                {
                    //gonna need this reviewed, not entirely sure this is OK to do
                    Log.Information($@"[{loggingPrefix}] Updating export {exportDelta.Value.InstancedFullPath}");

                    targetPackage.Exports[exportDelta.Key].Data   = exportDelta.Value.Data;
                    targetPackage.Exports[exportDelta.Key].Header = exportDelta.Value.Header;
                }
            }

            foreach (var importDelta in vanillaToModifiedDelta.ImportDeltas)
            {
                if (importDelta.Key >= targetPackage.ImportCount)
                {
                    //add it
                    Log.Information($@"[{loggingPrefix}] Adding import {importDelta.Value.InstancedFullPath}");

                    targetPackage.AddImport(importDelta.Value); //not sure if this is possible
                }
                else
                {
                    Log.Information($@"[{loggingPrefix}] Updating import {importDelta.Value.InstancedFullPath}");

                    //gonna need this reviewed, not entirely sure this is OK to do
                    //targetPackage.Imports[importDelta.Key].Data = importDelta.Value.Data;
                    targetPackage.Imports[importDelta.Key].Header = importDelta.Value.Header;
                }
            }

            Log.Information($@"[{loggingPrefix}] Finished three way merge");
            return(true);
        }
Example #22
0
 public static void WriteStructProperty(this Stream stream, IMEPackage pcc, string propName, string structName, MemoryStream value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.StructProperty, (int)value.Length);
     stream.WriteValueS32(pcc.FindNameOrAdd(structName));
     stream.WriteValueS32(0);
     stream.WriteStream(value);
 }
Example #23
0
 public static void WriteByteProperty(this Stream stream, IMEPackage pcc, string propName, byte value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 1);
     if (pcc.Game == MEGame.ME3)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd("None"));
         stream.WriteValueS32(0);
     }
     stream.WriteByte(value);
 }
Example #24
0
 public static void WriteEnumProperty(this Stream stream, IMEPackage pcc, string propName, string enumName, string enumValue, int index = 0)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 8);
     if (pcc.Game == MEGame.ME3)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd(enumName));
         stream.WriteValueS32(0); 
     }
     stream.WriteValueS32(pcc.FindNameOrAdd(enumValue));
     stream.WriteValueS32(index);
 }
Example #25
0
        /// <summary>
        /// Adds an import from the importingPCC to the destinationPCC with the specified importFullName, or returns the existing one if it can be found.
        /// This method will look at importingPCC's import upstream chain and check for the most downstream one's existence in destinationPCC,
        /// including if none can be founc (in which case the entire upstream is copied). It will then create new imports to match the remaining
        /// downstream ones and return the originally named import, however now located in destinationPCC.
        /// </summary>
        /// <param name="importFullName">GetFullPath() of an import from ImportingPCC</param>
        /// <param name="importingPCC">PCC to import imports from</param>
        /// <param name="destinationPCC">PCC to add imports to</param>
        /// <returns></returns>
        private ImportEntry getOrAddCrossImport(string importFullName, IMEPackage importingPCC, IMEPackage destinationPCC, int?forcedLinkIdx = null)
        {
            //This code is kind of ugly, sorry.

            //see if this import exists locally
            foreach (ImportEntry imp in destinationPCC.Imports)
            {
                if (imp.GetFullPath == importFullName)
                {
                    return(imp);
                }
            }

            //Import doesn't exist, so we're gonna need to add it
            //But first we need to figure out what needs to be added upstream as links
            //Search upstream until we find something, or we can't get any more upstreams
            ImportEntry mostdownstreamimport = null;

            string[] importParts = importFullName.Split('.');

            if (!forcedLinkIdx.HasValue)
            {
                List <int> upstreamLinks = new List <int>(); //0 = top level, 1 = next level... n = what we wanted to import
                int        upstreamCount = 1;

                ImportEntry upstreamImport = null;
                //get number of required upstream imports that do not yet exist
                while (upstreamCount < importParts.Count())
                {
                    string upstream = String.Join(".", importParts, 0, importParts.Count() - upstreamCount);
                    foreach (ImportEntry imp in destinationPCC.Imports)
                    {
                        if (imp.GetFullPath == upstream)
                        {
                            upstreamImport = imp;
                            break;
                        }
                    }

                    if (upstreamImport != null)
                    {
                        //We found an upsteam import that already exists
                        break;
                    }
                    upstreamCount++;
                }

                IExportEntry donorUpstreamExport = null;
                if (upstreamImport == null)
                {
                    //We have to import the entire upstream chain
                    string      fullobjectname      = importParts[0];
                    ImportEntry donorTopLevelImport = null;
                    foreach (ImportEntry imp in importingPCC.Imports) //importing side info we will move to our dest pcc
                    {
                        if (imp.GetFullPath == fullobjectname)
                        {
                            donorTopLevelImport = imp;
                            break;
                        }
                    }

                    if (donorTopLevelImport == null)
                    {
                        //This is issue KinkoJiro had. It is aborting relinking at this step. Will need to find a way to
                        //work with exports as parents for imports which will block it.
                        //Update: This has been partially implemented.
                        Debug.WriteLine("No upstream import was found in the source file. It's probably an export: " + importFullName);
                        foreach (IExportEntry exp in destinationPCC.Exports) //importing side info we will move to our dest pcc
                        {
                            //Console.WriteLine(exp.GetFullPath);
                            if (exp.GetFullPath == fullobjectname)
                            {
                                // = imp;
                                //We will need to find a way to cross map this as this will block cross import mapping unless these exports already exist.
                                Debug.WriteLine("FOUND UPSTREAM, AS EXPORT!");
                                KFreonLib.Debugging.DebugOutput.StartDebugger("Package Editor Relinker");
                                KFreonLib.Debugging.DebugOutput.PrintLn("Error: Upstream item that is required is an export in the pcc to import from: " + fullobjectname);
                                donorUpstreamExport = exp;
                                upstreamCount--; //level 1 now from the top down
                                                 //Create new import with this as higher IDK
                                break;
                            }
                        }
                        if (donorUpstreamExport == null)
                        {
                            Debug.WriteLine("An error has occured. Could not find an upstream import or export for relinking: " + fullobjectname + " from " + pcc.FileName);
                            return(null);
                        }
                    }

                    if (donorUpstreamExport == null)
                    {
                        //Create new toplevel import and set that as the most downstream one. (top = bottom at this point)
                        int downstreamPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(donorTopLevelImport.PackageFile));
                        int downstreamClassName   = destinationPCC.FindNameOrAdd(donorTopLevelImport.ClassName);
                        int downstreamName        = destinationPCC.FindNameOrAdd(fullobjectname);

                        mostdownstreamimport = new ImportEntry(destinationPCC);
                        // mostdownstreamimport.idxLink = downstreamLinkIdx; ??
                        mostdownstreamimport.idxClassName   = downstreamClassName;
                        mostdownstreamimport.idxObjectName  = downstreamName;
                        mostdownstreamimport.idxPackageFile = downstreamPackageFile;
                        destinationPCC.addImport(mostdownstreamimport); //Add new top level downstream import
                        upstreamImport = mostdownstreamimport;
                        upstreamCount--;                                //level 1 now from the top down
                                                                        //return null;
                    }
                }

                //Have an upstream import, now we need to add downstream imports.
                while (upstreamCount > 0)
                {
                    upstreamCount--;
                    string      fullobjectname = String.Join(".", importParts, 0, importParts.Count() - upstreamCount);
                    ImportEntry donorImport    = null;

                    //Get or create names for creating import and get upstream linkIdx
                    int downstreamName = destinationPCC.FindNameOrAdd(importParts[importParts.Count() - upstreamCount - 1]);
                    foreach (ImportEntry imp in importingPCC.Imports) //importing side info we will move to our dest pcc
                    {
                        if (imp.GetFullPath == fullobjectname)
                        {
                            donorImport = imp;
                            break;
                        }
                    }
                    if (donorImport == null)
                    {
                        throw new Exception("No suitable upstream import was found for porting - this may be an export in the source file that is referenced as a parent or dependency. You should import this object and its parents first. " + fullobjectname + "(as part of " + importFullName + ")");
                    }

                    int downstreamPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(donorImport.PackageFile));
                    int downstreamClassName   = destinationPCC.FindNameOrAdd(donorImport.ClassName);

                    mostdownstreamimport                = new ImportEntry(destinationPCC);
                    mostdownstreamimport.idxLink        = donorUpstreamExport == null ? upstreamImport.UIndex : donorUpstreamExport.UIndex;
                    mostdownstreamimport.idxClassName   = downstreamClassName;
                    mostdownstreamimport.idxObjectName  = downstreamName;
                    mostdownstreamimport.idxPackageFile = downstreamPackageFile;
                    destinationPCC.addImport(mostdownstreamimport);
                    upstreamImport = mostdownstreamimport;
                }
            }
            else
            {
                //get importing import
                ImportEntry importingImport = importingPCC.Imports.FirstOrDefault(x => x.GetFullPath == importFullName); //this shouldn't be null
                mostdownstreamimport                = new ImportEntry(destinationPCC);
                mostdownstreamimport.idxLink        = forcedLinkIdx.Value;
                mostdownstreamimport.idxClassName   = destinationPCC.FindNameOrAdd(importingImport.ClassName);
                mostdownstreamimport.idxObjectName  = destinationPCC.FindNameOrAdd(importingImport.ObjectName);
                mostdownstreamimport.idxPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(importingImport.PackageFile));
                destinationPCC.addImport(mostdownstreamimport);
            }
            return(mostdownstreamimport);
        }
Example #26
0
        public static IEntry GetEntryOrAddImport(IMEPackage Pcc, string importFullName)
        {
            //foreach (ImportEntry imp in Pcc.Imports)
            //{
            //    if (imp.GetFullPath == importFullName)
            //    {
            //        return imp;
            //    }
            //}

            var fullPathMappingList = new List <(string fullpath, IEntry entry)>();

            foreach (ImportEntry imp in Pcc.Imports)
            {
                fullPathMappingList.Add((imp.GetFullPath, imp));
            }
            foreach (ExportEntry exp in Pcc.Exports)
            {
                fullPathMappingList.Add((exp.GetFullPath, exp));
            }

            var directMapping = fullPathMappingList.Where(x => x.fullpath == importFullName).ToList();

            if (directMapping.Count == 1)
            {
                return(directMapping[0].entry);                          //direct single match
            }
            //Find an upstream entry to attach our import to (we can't add exports)
            string[] importParts   = importFullName.Split('.');
            int      upstreamCount = 1;

            IEntry upstreamEntryToAttachTo = null;
            string upstreamfullpath;

            while (upstreamCount < importParts.Length)
            {
                upstreamfullpath = string.Join(".", importParts, 0, importParts.Length - upstreamCount);
                var upstreammatchinglist = fullPathMappingList.Where(x => x.fullpath == upstreamfullpath).ToList();
                if (upstreammatchinglist.Where(x => x.entry is ExportEntry).HasExactly(1) || upstreammatchinglist.Where(x => x.entry is ImportEntry).HasExactly(1))
                {
                    upstreamEntryToAttachTo = upstreammatchinglist[0].entry;
                    break;
                }

                /*if (upstreamEntryToAttachTo != null)
                 * {
                 *  break;
                 * }*/
                upstreamCount++;
            }

            //upstreamImport = Pcc.Imports.FirstOrDefault(x => x.GetFullPath == upstream);



            //Check if this is an export instead

            /* itemAsImport = Pcc.Exports.FirstOrDefault(x => x.GetFullPath == importFullName && x.indexValue == 0);
             * if (itemAsImport != null)
             * {
             *  return itemAsImport;
             * }*/

            //Import doesn't exist, so we're gonna need to add it
            //But first we need to figure out what needs to be added.
            //string[] importParts = importFullName.Split('.');
            //List<int> upstreamLinks = new List<int>(); //0 = top level, 1 = next level... n = what we wanted to import

            /*ImportEntry upstreamImport = null;
             * string upstream = null;
             * while (upstreamCount < importParts.Count())
             * {
             *  upstreamfullpath = string.Join(".", importParts, 0, importParts.Count() - upstreamCount);
             *  upstreamImport = Pcc.Imports.FirstOrDefault(x => x.GetFullPath == upstreamfullpath);
             *
             *  if (upstreamImport != null)
             *  {
             *      break;
             *  }
             *  upstreamCount++;
             * }*/

            if (upstreamEntryToAttachTo == null)
            {
                //There is nothing we can attach to.
                Debug.WriteLine("cannot find a top level item to attach to for " + importFullName);
                return(null);
            }

            //Have an upstream import, now we need to add downstream imports.
            ImportEntry mostdownstreamimport = null;

            while (upstreamCount > 0)
            {
                upstreamCount--;
                string fullobjectname = String.Join(".", importParts, 0, importParts.Length - upstreamCount);
                Dictionary <string, string> importdbinfo = ImportClassDB[fullobjectname];

                int downstreamName = Pcc.FindNameOrAdd(importParts[importParts.Length - upstreamCount - 1]);
                Debug.WriteLine(Pcc.Names[downstreamName]);
                int downstreamLinkIdx = upstreamEntryToAttachTo.UIndex;
                Debug.WriteLine(upstreamEntryToAttachTo.GetFullPath);

                int    downstreamPackageName = Pcc.FindNameOrAdd(importdbinfo["packagefile"]);
                string downstreamClassName   = importdbinfo["fullclasspath"];
                int    lastPeriodIndex       = downstreamClassName.LastIndexOf(".");
                if (lastPeriodIndex > 0)
                {
                    downstreamClassName = importdbinfo["fullclasspath"].Substring(lastPeriodIndex + 1);
                }

                int downstreamClassNameIdx = Pcc.FindNameOrAdd(downstreamClassName);
                Debug.WriteLine("Finding name " + downstreamClassName);
                //ImportEntry classImport = getOrAddImport();
                //int downstreamClass = 0;
                //if (classImport != null) {
                //    downstreamClass = classImport.UIndex; //no recursion pls
                //} else
                //{
                //    throw new Exception("No class was found for importing");
                //}

                mostdownstreamimport = new ImportEntry(Pcc)
                {
                    idxLink        = downstreamLinkIdx,
                    idxClassName   = downstreamClassNameIdx,
                    idxObjectName  = downstreamName,
                    idxPackageFile = downstreamPackageName
                };
                Pcc.addImport(mostdownstreamimport);
                upstreamEntryToAttachTo = mostdownstreamimport;
            }
            return(mostdownstreamimport);
        }
 public static void WriteNoneProperty(this Stream stream, IMEPackage pcc)
 {
     stream.WriteValueS32(pcc.FindNameOrAdd("None"));
     stream.WriteValueS32(0);
 }
        public static void ImportProperty(IMEPackage pcc, IMEPackage importpcc, Property p, string className, MemoryStream m, bool inStruct = false)
        {
            string name    = importpcc.getNameEntry(p.Name);
            int    idxname = pcc.FindNameOrAdd(name);

            m.Write(BitConverter.GetBytes(idxname), 0, 4);
            m.Write(new byte[4], 0, 4);
            if (name == "None")
            {
                return;
            }
            string type    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 8));
            int    idxtype = pcc.FindNameOrAdd(type);

            m.Write(BitConverter.GetBytes(idxtype), 0, 4);
            m.Write(new byte[4], 0, 4);
            string          name2;
            int             idxname2;
            int             size, count, pos;
            List <Property> Props;

            switch (type)
            {
            case "IntProperty":
            case "FloatProperty":
            case "ObjectProperty":
            case "StringRefProperty":
                m.Write(BitConverter.GetBytes(4), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(p.Value.IntValue), 0, 4);
                break;

            case "NameProperty":
                m.Write(BitConverter.GetBytes(8), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                //preserve index or whatever the second part of a namereference is
                m.Write(p.raw, 28, 4);
                break;

            case "BoolProperty":
                m.Write(new byte[8], 0, 8);
                m.WriteByte((byte)p.Value.IntValue);
                if (pcc.Game != MEGame.ME3)
                {
                    m.Write(new byte[3], 0, 3);
                }
                break;

            case "BioMask4Property":
                m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.WriteByte((byte)p.Value.IntValue);
                break;

            case "ByteProperty":
                m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                m.Write(new byte[4], 0, 4);
                if (pcc.Game == MEGame.ME3)
                {
                    name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                    idxname2 = pcc.FindNameOrAdd(name2);
                    m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                if (p.Size != 1)
                {
                    m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                else
                {
                    m.WriteByte(Convert.ToByte(p.Value.IntValue));
                }
                break;

            case "DelegateProperty":
                size = BitConverter.ToInt32(p.raw, 16);
                if (size == 0xC)
                {
                    name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28));
                    idxname2 = pcc.FindNameOrAdd(name2);
                    m.Write(BitConverter.GetBytes(0xC), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                else
                {
                    m.Write(BitConverter.GetBytes(size), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    for (int i = 0; i < size; i++)
                    {
                        m.WriteByte(p.raw[24 + i]);
                    }
                }
                break;

            case "StrProperty":
                name2 = p.Value.StringValue;
                if (p.Value.StringValue.Length > 0)
                {
                    name2 += '\0';
                }
                if (p.Value.len < 0)
                {
                    //unicode
                    m.Write(BitConverter.GetBytes(4 + name2.Length * 2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(-name2.Length), 0, 4);
                    foreach (char c in name2)
                    {
                        m.WriteByte((byte)c);
                        m.WriteByte(0);
                    }
                }
                else
                {
                    //ascii
                    m.Write(BitConverter.GetBytes(4 + name2.Length), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(name2.Length), 0, 4);
                    foreach (char c in name2)
                    {
                        m.WriteByte((byte)c);
                    }
                }
                break;

            case "StructProperty":
                size     = BitConverter.ToInt32(p.raw, 16);
                name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                idxname2 = pcc.FindNameOrAdd(name2);
                pos      = 32;
                Props    = new List <Property>();
                try
                {
                    Props = ReadProp(importpcc, p.raw, pos);
                }
                catch (Exception)
                {
                }
                m.Write(BitConverter.GetBytes(size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                m.Write(new byte[4], 0, 4);
                if (Props.Count == 0 || Props[0].TypeVal == PropertyType.Unknown)
                {
                    for (int i = 0; i < size; i++)
                    {
                        m.WriteByte(p.raw[32 + i]);
                    }
                }
                else
                {
                    foreach (Property pp in Props)
                    {
                        ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                }
                break;

            case "ArrayProperty":
                size  = BitConverter.ToInt32(p.raw, 16);
                count = BitConverter.ToInt32(p.raw, 24);
                PropertyInfo info      = ME3UnrealObjectInfo.getPropertyInfo(className, name, inStruct);
                ArrayType    arrayType = ME3UnrealObjectInfo.getArrayType(info);
                pos = 28;
                List <Property> AllProps = new List <Property>();

                if (arrayType == ArrayType.Struct)
                {
                    for (int i = 0; i < count; i++)
                    {
                        Props = new List <Property>();
                        try
                        {
                            Props = ReadProp(importpcc, p.raw, pos);
                        }
                        catch (Exception)
                        {
                        }
                        AllProps.AddRange(Props);
                        if (Props.Count != 0)
                        {
                            pos = Props[Props.Count - 1].offend;
                        }
                    }
                }
                m.Write(BitConverter.GetBytes(size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(count), 0, 4);
                if (AllProps.Count != 0 && (info == null || !UnrealObjectInfo.isImmutable(info.reference, pcc.Game)))
                {
                    foreach (Property pp in AllProps)
                    {
                        ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                }
                else if (arrayType == ArrayType.Name)
                {
                    for (int i = 0; i < count; i++)
                    {
                        string s = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28 + i * 8));
                        m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(s)), 0, 4);
                        //preserve index or whatever the second part of a namereference is
                        m.Write(p.raw, 32 + i * 8, 4);
                    }
                }
                else
                {
                    m.Write(p.raw, 28, size - 4);
                }
                break;

            default:
                throw new Exception(type);
            }
        }
Example #29
0
 public static void WritePropHeader(this Stream stream, IMEPackage pcc, string propName, PropertyType type, int size)
 {
     stream.WriteValueS32(pcc.FindNameOrAdd(propName));
     stream.WriteValueS32(0);
     stream.WriteValueS32(pcc.FindNameOrAdd(type.ToString()));
     stream.WriteValueS32(0);
     stream.WriteValueS32(size);
     stream.WriteValueS32(0);
 }
Example #30
0
 public static void WriteEnumProperty(this Stream stream, IMEPackage pcc, string propName, NameReference enumName, NameReference enumValue)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 8);
     if (pcc.Game == MEGame.ME3)
     {
         stream.WriteValueS32(pcc.FindNameOrAdd(enumName.Name));
         stream.WriteValueS32(enumName.count);
     }
     stream.WriteValueS32(pcc.FindNameOrAdd(enumValue.Name));
     stream.WriteValueS32(enumValue.count);
 }
Example #31
0
 public static void WriteDelegateProperty(this Stream stream, IMEPackage pcc, string propName, int unk, NameReference value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.DelegateProperty, 12);
     stream.WriteValueS32(unk);
     stream.WriteValueS32(pcc.FindNameOrAdd(value.Name));
     stream.WriteValueS32(value.count);
 }
 public static void WriteNameProperty(this Stream stream, IMEPackage pcc, string propName, NameReference value)
 {
     stream.WritePropHeader(pcc, propName, PropertyType.NameProperty, 8);
     stream.WriteValueS32(pcc.FindNameOrAdd(value.Name));
     stream.WriteValueS32(value.count);
 }
Example #33
0
 protected void WriteName(string fullName)
 {
     (string name, int number) = StringToNameRef(fullName);
     WriteInt(Pcc.FindNameOrAdd(name));
     WriteInt(number);
 }
Example #34
0
        /// <summary>
        /// Adds an import from the importingPCC to the destinationPCC with the specified importFullName, or returns the existing one if it can be found.
        /// This will add parent imports and packages as neccesary
        /// </summary>
        /// <param name="importFullName">GetFullPath() of an import from ImportingPCC</param>
        /// <param name="importingPCC">PCC to import imports from</param>
        /// <param name="destinationPCC">PCC to add imports to</param>
        /// <param name="forcedLink">force this as parent</param>
        /// <returns></returns>
        public static IEntry getOrAddCrossImportOrPackage(string importFullName, IMEPackage importingPCC, IMEPackage destinationPCC, int?forcedLink = null)
        {
            if (string.IsNullOrEmpty(importFullName))
            {
                return(null);
            }

            //see if this import exists locally
            foreach (ImportEntry imp in destinationPCC.Imports)
            {
                if (imp.GetFullPath == importFullName)
                {
                    return(imp);
                }
            }

            //see if this is an export Package and exists locally
            foreach (ExportEntry exp in destinationPCC.Exports)
            {
                if (exp.ClassName == "Package" && exp.GetFullPath == importFullName)
                {
                    return(exp);
                }
            }

            if (forcedLink is int link)
            {
                ImportEntry importingImport = importingPCC.Imports.First(x => x.GetFullPath == importFullName); //this shouldn't be null
                var         newImport       = new ImportEntry(destinationPCC)
                {
                    idxLink        = link,
                    idxClassName   = destinationPCC.FindNameOrAdd(importingImport.ClassName),
                    idxObjectName  = destinationPCC.FindNameOrAdd(importingImport.ObjectName),
                    idxPackageFile = destinationPCC.FindNameOrAdd(importingImport.PackageFile)
                };
                destinationPCC.addImport(newImport);
                return(newImport);
            }

            string[] importParts = importFullName.Split('.');

            //recursively ensure parent package exists. when importParts.Length == 1, this will return null
            IEntry parent = getOrAddCrossImportOrPackage(string.Join(".", importParts.Take(importParts.Length - 1)), importingPCC, destinationPCC);


            foreach (ImportEntry imp in importingPCC.Imports)
            {
                if (imp.GetFullPath == importFullName)
                {
                    var import = new ImportEntry(destinationPCC)
                    {
                        idxLink        = parent?.UIndex ?? 0,
                        idxClassName   = destinationPCC.FindNameOrAdd(imp.ClassName),
                        idxObjectName  = destinationPCC.FindNameOrAdd(imp.ObjectName),
                        idxPackageFile = destinationPCC.FindNameOrAdd(imp.PackageFile)
                    };
                    destinationPCC.addImport(import);
                    return(import);
                }
            }

            foreach (ExportEntry exp in importingPCC.Exports)
            {
                if (exp.ClassName == "Package" && exp.GetFullPath == importFullName)
                {
                    importExport(destinationPCC, exp, parent?.UIndex ?? 0, out ExportEntry package);
                    return(package);
                }
            }

            throw new Exception($"Unable to add {importFullName} to file! Could not find it!");
        }
Example #35
0
 public static void WriteNameReference(this Stream stream, NameReference name, IMEPackage pcc)
 {
     stream.WriteInt32(pcc.FindNameOrAdd(name.Name));
     stream.WriteInt32(name.Number);
 }
Example #36
0
        public static void ImportProperty(IMEPackage pcc, IMEPackage importpcc, Property p, string className, MemoryStream m, bool inStruct = false)
        {
            string name = importpcc.getNameEntry(p.Name);
            int idxname = pcc.FindNameOrAdd(name);
            m.Write(BitConverter.GetBytes(idxname), 0, 4);
            m.Write(new byte[4], 0, 4);
            if (name == "None")
                return;
            string type = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 8));
            int idxtype = pcc.FindNameOrAdd(type);
            m.Write(BitConverter.GetBytes(idxtype), 0, 4);
            m.Write(new byte[4], 0, 4);
            string name2;
            int idxname2;
            int size, count, pos;
            List<Property> Props;
            switch (type)
            {
                case "IntProperty":
                case "FloatProperty":
                case "ObjectProperty":
                case "StringRefProperty":
                    m.Write(BitConverter.GetBytes(4), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(p.Value.IntValue), 0, 4);
                    break;
                case "NameProperty":
                    m.Write(BitConverter.GetBytes(8), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                    //preserve index or whatever the second part of a namereference is
                    m.Write(p.raw, 28, 4);
                    break;
                case "BoolProperty":
                    m.Write(new byte[8], 0, 8);
                    m.WriteByte((byte)p.Value.IntValue);
                    if (pcc.Game != MEGame.ME3)
                    {
                        m.Write(new byte[3], 0, 3);
                    }
                    break;
                case "BioMask4Property":
                    m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.WriteByte((byte)p.Value.IntValue);
                    break;
                case "ByteProperty":
                    m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    if (pcc.Game == MEGame.ME3)
                    {
                        name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                        idxname2 = pcc.FindNameOrAdd(name2);
                        m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                        m.Write(new byte[4], 0, 4);
                    }
                    if (p.Size != 1)
                    {
                        m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                        m.Write(new byte[4], 0, 4);
                    }
                    else
                    {
                        m.WriteByte(Convert.ToByte(p.Value.IntValue));
                    }
                    break;
                case "DelegateProperty":
                    size = BitConverter.ToInt32(p.raw, 16);
                    if (size == 0xC)
                    {
                        name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28));
                        idxname2 = pcc.FindNameOrAdd(name2);
                        m.Write(BitConverter.GetBytes(0xC), 0, 4);
                        m.Write(new byte[4], 0, 4);
                        m.Write(new byte[4], 0, 4);
                        m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                        m.Write(new byte[4], 0, 4);
                    }
                    else
                    {
                        m.Write(BitConverter.GetBytes(size), 0, 4);
                        m.Write(new byte[4], 0, 4);
                        for (int i = 0; i < size; i++)
                            m.WriteByte(p.raw[24 + i]);
                    }
                    break;
                case "StrProperty":
                    name2 = p.Value.StringValue + '\0';
                    if (p.Value.len < 0)
                    {
                        m.Write(BitConverter.GetBytes(4 + name2.Length * 2), 0, 4);
                        m.Write(new byte[4], 0, 4);
                        m.Write(BitConverter.GetBytes(-name2.Length), 0, 4);
                        foreach (char c in name2)
                        {
                            m.WriteByte((byte)c);
                            m.WriteByte(0);
                        } 
                    }
                    else
                    {
                        m.Write(BitConverter.GetBytes(4 + name2.Length), 0, 4);
                        m.Write(new byte[4], 0, 4);
                        m.Write(BitConverter.GetBytes(name2.Length), 0, 4);
                        foreach (char c in name2)
                        {
                            m.WriteByte((byte)c);
                        }
                    }
                    break;
                case "StructProperty":
                    size = BitConverter.ToInt32(p.raw, 16);
                    name2 = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                    idxname2 = pcc.FindNameOrAdd(name2);
                    pos = 32;
                    Props = new List<Property>();
                    try
                    {
                        Props = ReadProp(importpcc, p.raw, pos);
                    }
                    catch (Exception)
                    {
                    }
                    m.Write(BitConverter.GetBytes(size), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    if (Props.Count == 0 || Props[0].TypeVal == PropertyType.Unknown)
                    {
                        for (int i = 0; i < size; i++)
                            m.WriteByte(p.raw[32 + i]);
                    }
                    else
                    {
                        foreach (Property pp in Props)
                            ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                    break;
                case "ArrayProperty":
                    size = BitConverter.ToInt32(p.raw, 16);
                    count = BitConverter.ToInt32(p.raw, 24);
                    PropertyInfo info = ME3UnrealObjectInfo.getPropertyInfo(className, name, inStruct);
                    ArrayType arrayType = ME3UnrealObjectInfo.getArrayType(info);
                    pos = 28;
                    List<Property> AllProps = new List<Property>();

                    if (arrayType == ArrayType.Struct)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            Props = new List<Property>();
                            try
                            {
                                Props = ReadProp(importpcc, p.raw, pos);
                            }
                            catch (Exception)
                            {
                            }
                            AllProps.AddRange(Props);
                            if (Props.Count != 0)
                            {
                                pos = Props[Props.Count - 1].offend;
                            }
                        }
                    }
                    m.Write(BitConverter.GetBytes(size), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(count), 0, 4);
                    if (AllProps.Count != 0 && (info == null || !ME3UnrealObjectInfo.isImmutable(info.reference)))
                    {
                        foreach (Property pp in AllProps)
                            ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                    else if (arrayType == ArrayType.Name)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            string s = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28 + i * 8));
                            m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(s)), 0, 4);
                            //preserve index or whatever the second part of a namereference is
                            m.Write(p.raw, 32 + i * 8, 4);
                        }
                    }
                    else
                    {
                        m.Write(p.raw, 28, size - 4);
                    }
                    break;
                default:
                    throw new Exception(type);
            }
        }