public static (string, bool, EProjectFolders) GetModRelativePath(this string fullpath, string activeModFileDirectory) { var relativePath = fullpath.Substring(activeModFileDirectory.Length + 1); bool isDLC; EProjectFolders projectfolder = EProjectFolders.Cooked; if (relativePath.StartsWith("DLC\\")) { isDLC = true; } else if (relativePath.StartsWith("Mod\\")) { isDLC = false; } else { throw new NotImplementedException(); } relativePath = relativePath.Substring(4); if (relativePath.StartsWith(EProjectFolders.Cooked.ToString())) { relativePath = relativePath.Substring(EProjectFolders.Cooked.ToString().Length + 1); projectfolder = EProjectFolders.Cooked; } if (relativePath.StartsWith(EProjectFolders.Uncooked.ToString())) { relativePath = relativePath.Substring(EProjectFolders.Uncooked.ToString().Length + 1); projectfolder = EProjectFolders.Uncooked; } else if (relativePath.StartsWith(EBundleType.SoundCache.ToString())) { relativePath = relativePath.Substring(EBundleType.SoundCache.ToString().Length + 1); } else if (relativePath.StartsWith(EBundleType.Speech.ToString())) { relativePath = relativePath.Substring(EBundleType.Speech.ToString().Length + 1); } return(relativePath, isDLC, projectfolder); }
/// <summary> /// Adds all file dependencies (cr2w imports) to a specified folder /// retaining relative paths /// </summary> /// <param name="importfilepath"></param> /// <param name="recursive"></param> /// <param name="silent"></param> /// <param name="alternateOutDirectory"></param> /// <returns></returns> public static async Task AddAllImports(string importfilepath, bool recursive = false, bool silent = false, string alternateOutDirectory = "", bool logonly = false) { if (!File.Exists(importfilepath)) { return; } string relativepath = ""; bool isDLC = false; EProjectFolders projectFolder = EProjectFolders.Uncooked; if (string.IsNullOrWhiteSpace(alternateOutDirectory)) { (relativepath, isDLC, projectFolder) = importfilepath.GetModRelativePath(ActiveMod.FileDirectory); } else { relativepath = importfilepath.Substring(alternateOutDirectory.Length + 1); } List <CR2WImportWrapper> importslist = new List <CR2WImportWrapper>(); List <CR2WBufferWrapper> bufferlist = new List <CR2WBufferWrapper>(); bool hasinternalBuffer; using (var fs = new FileStream(importfilepath, FileMode.Open, FileAccess.Read)) using (var reader = new BinaryReader(fs)) { var cr2w = new CR2WFile(); (importslist, hasinternalBuffer, bufferlist) = cr2w.ReadImportsAndBuffers(reader); } bool success = true; // add imports foreach (var import in importslist) { var filename = Path.GetFileName(import.DepotPathStr); if (logonly) { MainController.LogString(filename, Logtype.Important); } var path = UnbundleFile(import.DepotPathStr, isDLC, projectFolder, EArchiveType.Bundle, alternateOutDirectory, false, silent); // If unbundled file is xbm, also extract tga from texturecache if (Path.GetExtension(import.DepotPathStr) == ".xbm") { UnbundleFile(import.DepotPathStr, isDLC, EProjectFolders.Raw, EArchiveType.TextureCache, alternateOutDirectory, false, silent); } if (string.IsNullOrWhiteSpace(path)) { Logger.LogString($"Did not unbundle {filename}, import is missing.", Logtype.Error); } else { // recursively add all 1st order dependencies :Gp: if (recursive) { AddAllImports(path, true, silent, alternateOutDirectory, logonly); } } } // add buffers if (hasinternalBuffer) { Logger.LogString($"{Path.GetFileName(importfilepath)} has internal buffers. If you need external buffers, unbundle them manually.", Logtype.Important); } else { // unbundle external buffers foreach (CR2WBufferWrapper buffer in bufferlist) { var index = buffer.Buffer.index; string bufferpath = $"{relativepath}.{index}.buffer"; var bufferName = $"{Path.GetFileName(relativepath)}.{index}.buffer"; var path = UnbundleFile(bufferpath, isDLC, projectFolder, EArchiveType.Bundle, alternateOutDirectory, false, silent); if (string.IsNullOrWhiteSpace(path)) { Logger.LogString($"Did not unbundle {bufferName}, import is missing.", Logtype.Error); } } } //if (success && !silent) // Logger.LogString($"Succesfully imported all dependencies.", Logtype.Success); }
/// <summary> /// Unbundles a file with the given relativepath from either the Game or the Mod BundleManager /// and adds it to the depot, optionally copying to the project /// </summary> /// <param name="relativePath"></param> /// <param name="isDLC"></param> /// <param name="projectFolder"></param> /// <param name="bundleType"></param> /// <param name="alternateOutDirectory"></param> /// <param name="loadmods"></param> /// <param name="silent"></param> /// <returns></returns> public static string UnbundleFile(string relativePath, bool isDlc, EProjectFolders projectFolder, EArchiveType bundleType = EArchiveType.Bundle, string alternateOutDirectory = "", bool loadmods = false, bool silent = false) { string extension = Path.GetExtension(relativePath); string filename = Path.GetFileName(relativePath); // Jato said not to add textures to an fbx // so I am keeping meshes violet :) //if (extension == ".xbm" && bundleType == EBundleType.Archive) //{ // //var uncookTask = Task.Run(() => UncookFileToPath(relativePath, isDLC, alternateOutDirectory)); // //Task.WaitAll(uncookTask); // //return relativePath; // UnbundleFile(relativePath, isDLC, projectFolder, EBundleType.TextureCache, alternateOutDirectory, // loadmods, silent); //} IGameArchiveManager manager = MainController.Get().GetManagers(loadmods).FirstOrDefault(_ => _.TypeName == bundleType); if (manager != null && manager.Items.Any(x => x.Value.Any(y => y.Name == relativePath))) { var archives = manager.FileList .Where(x => x.Name == relativePath) .Select(y => new KeyValuePair <string, IGameFile>(y.Archive.ArchiveAbsolutePath, y)) .ToList(); // Extract try { // if more than one archive get the last var archive = archives.Last().Value; string newpath = ""; if (string.IsNullOrWhiteSpace(alternateOutDirectory)) { switch (projectFolder) { case EProjectFolders.Cooked: newpath = Path.Combine(isDlc ? ActiveMod.DlcCookedDirectory : ActiveMod.ModCookedDirectory, relativePath); break; case EProjectFolders.Uncooked: newpath = Path.Combine(isDlc ? ActiveMod.DlcUncookedDirectory : ActiveMod.ModUncookedDirectory, relativePath); break; case EProjectFolders.Raw: newpath = Path.Combine(isDlc ? ActiveMod.RawDlcDirectory : ActiveMod.RawModDirectory, relativePath); break; default: break; } } else { newpath = Path.Combine(alternateOutDirectory, relativePath); } if (string.IsNullOrWhiteSpace(newpath)) { return(""); } // for xbms check if a file with the current export extensions exists if (!File.Exists(newpath) && (extension != ".xbm" || !File.Exists(Path.ChangeExtension(newpath, MainController.Get().Configuration.UncookExtension.ToString())))) { string extractedfile = archive.Extract(new BundleFileExtractArgs(newpath, MainController.Get().Configuration.UncookExtension)); if (!silent) { Logger.LogString($"Succesfully unbundled {filename}.", Logtype.Success); } } //else // if (!silent) Logger.LogString($"File already exists in mod project: {filename}.", Logtype.Success); return(newpath); } catch (Exception ex) { Logger.LogString(ex.ToString(), Logtype.Error); return(""); } } return(""); }