/// <summary>
        /// Creates an ImportEntry that references the listed ExportEntry. Ensure the item will be in memory or this will crash the game!
        /// </summary>
        /// <param name="sourceExport"></param>
        /// <param name="targetPackage"></param>
        /// <returns></returns>
        public static ImportEntry CreateImportForClass(ExportEntry sourceExport, IMEPackage targetPackage, IEntry parentObject = null)
        {
            if (sourceExport.ClassName != "Class")
            {
                throw new Exception("Cannot reliably create import for non-class object!");
            }

            var existingImport = targetPackage.FindImport(sourceExport.InstancedFullPath);

            if (existingImport != null)
            {
                return(existingImport);
            }

            ImportEntry imp = new ImportEntry(targetPackage)
            {
                ObjectName  = sourceExport.ObjectName,
                PackageFile = "Core", //Risky...
                ClassName   = sourceExport.ClassName,
                idxLink     = parentObject?.UIndex ?? 0,
            };

            targetPackage.AddImport(imp);
            return(imp);
        }
        /// <summary>
        /// Converts an AnimSet export to an import
        /// </summary>
        /// <param name="origEntry"></param>
        /// <param name="targetPackage"></param>
        /// <returns></returns>
        private static IEntry ConvertAnimSetExportToImport(IEntry origEntry, IMEPackage targetPackage)
        {
            // Check if this item is available already
            var found = targetPackage.FindEntry(origEntry.InstancedFullPath);

            if (found != null)
            {
                return(found);
            }

            // Setup the link for our import
            var parentPackage = targetPackage.FindEntry(origEntry.Parent.InstancedFullPath);

            if (parentPackage == null)
            {
                // We must add a package import
                parentPackage = new ImportEntry(targetPackage)
                {
                    idxLink     = 0,
                    ClassName   = "Package",
                    ObjectName  = origEntry.Parent.ObjectName,
                    PackageFile = "Core"
                };
                targetPackage.AddImport((ImportEntry)parentPackage);
            }

            // Install the import
            ImportEntry imp = new ImportEntry(targetPackage)
            {
                ClassName   = origEntry.ClassName,
                idxLink     = parentPackage.UIndex,
                ObjectName  = origEntry.ObjectName,
                PackageFile = "Engine"
            };

            targetPackage.AddImport(imp);

            return(imp);
        }
        //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", int?objIdx = null)
        {
            if (string.IsNullOrEmpty(fullPath))
            {
                return(null);
            }

            //see if this import exists locally
            foreach (ImportEntry imp in pcc.Imports)
            {
                if (imp.FullPath == fullPath && (objIdx == null || objIdx == imp.ObjectName.Number))
                {
                    return(imp);
                }
            }

            //see if this is an export and exists locally
            foreach (ExportEntry exp in pcc.Exports)
            {
                if (exp.FullPath == fullPath && (objIdx == null || objIdx == exp.ObjectName.Number))
                {
                    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,
                ClassName   = className,
                ObjectName  = new NameReference(pathParts.Last(), objIdx ?? 0),
                PackageFile = packageFile
            };

            pcc.AddImport(import);
            return(import);
        }
Example #4
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.FullPath, imp));
            }
            foreach (ExportEntry exp in Pcc.Exports)
            {
                fullPathMappingList.Add((exp.FullPath, 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];

                var downstreamName = importParts[importParts.Length - upstreamCount - 1];
                Debug.WriteLine(downstreamName);
                int downstreamLinkIdx = upstreamEntryToAttachTo.UIndex;
                Debug.WriteLine(upstreamEntryToAttachTo.FullPath);

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

                //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,
                    ClassName   = downstreamClassName,
                    ObjectName  = downstreamName,
                    PackageFile = downstreamPackageName
                };
                Pcc.AddImport(mostdownstreamimport);
                upstreamEntryToAttachTo = mostdownstreamimport;
            }
            return(mostdownstreamimport);
        }
Example #5
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);
        }