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(); }
//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); }
/// <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); }
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); }
/// <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!"); }