/// <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);
        }
Exemple #2
0
        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.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    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.idxClass      = reachSpecClassImp.UIndex;
                    outgoingSpec.idxObjectName = reachSpecClassImp.idxObjectName;

                    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.idxClass      = reachSpecClassImp.UIndex;
                        incomingSpec.idxObjectName = reachSpecClassImp.idxObjectName;
                        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);
                }
            }
        }
Exemple #3
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);
        }