diff --git a/PSArcTool/Functions.cs b/PSArcTool/Functions.cs index a8aaeff..3b70b25 100644 --- a/PSArcTool/Functions.cs +++ b/PSArcTool/Functions.cs @@ -32,6 +32,43 @@ public static void Extract(string pakFilePath) } } + public static List ListContents(string pakFilePath) + { + var path = Path.GetTempFileName() + ".exe"; // Actually PSARC.EXE, but we just call it something random just cause. + File.WriteAllBytes(path, Properties.Resources.psarc); + var pakFile = new FileInfo(pakFilePath); + + List pakContents = new List(); + + if (pakFile.Exists) + { + var psarcArgs = string.Format("list \"{0}\"", pakFile.FullName); + var proc = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = path, + Arguments = psarcArgs, + UseShellExecute = false, + RedirectStandardOutput = true, + CreateNoWindow = true + } + }; + proc.Start(); + while (!proc.StandardOutput.EndOfStream) + { + string line = proc.StandardOutput.ReadLine(); + if (!line.StartsWith("Listing")) + { + if (line.StartsWith("/")) + line = line.Substring(1); + pakContents.Add(line.Split(' ')[0]); + } + } + } + return pakContents; + } + public static void Create(string dirPath) { if (Directory.Exists(dirPath)) @@ -40,7 +77,7 @@ public static void Create(string dirPath) } } - public static void Create(IList paths, string rootPath = null) + public static void Create(IList paths, string rootPath = null, string fname = "psarc.pak") { if (paths.Any() && paths.All(path => File.Exists(path) || Directory.Exists(path))) { @@ -86,7 +123,7 @@ public static void Create(IList paths, string rootPath = null) } } Run( - string.Format("create -a --zlib --inputfile=\"{0}\" --output={1}", tmpFilePath, "psarc.pak"), + string.Format("create -a --zlib --inputfile=\"{0}\" --output={1}", tmpFilePath, fname), rootPath); } } diff --git a/PSArcTool/Program.cs b/PSArcTool/Program.cs index 78bedbc..718e128 100644 --- a/PSArcTool/Program.cs +++ b/PSArcTool/Program.cs @@ -3,6 +3,8 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Collections.Generic; +using System.Threading; namespace PSArcTool { @@ -19,10 +21,39 @@ static void Main(string[] args) Console.WriteLine("PSArcTool"); Console.WriteLine("Periander 2016-08-17"); Console.WriteLine("I was mucking around with No Man's Sky modding and wanted to make extracting/creating PAK files easier."); - foreach (var arg in args) + Console.WriteLine("Modified by monkeyman192 to allow for mod conflict checking (use the arg -list for a simple list, and -listall for a detailed breakdown of clashes)"); + + // let's go through the arguments and see if we have any kwargs + // possibilities: + // out=fname - this is the name of the output pak file + // -list - this will return a list of all files in the pak file + string fname = ""; + bool returnlist = false; + string returnlistmode = "concise"; + foreach (string arg in args) { - Console.WriteLine(arg); + if (arg.Contains("out=")) + { + fname = String.Format("{0}.pak", arg.Substring(4)); + args = args.Where(val => val != arg).ToArray(); + } + else + fname = "psarc.pak"; + if (arg == "-list" || arg == "-listall") + { + returnlist = true; + if (arg == "-list") + returnlistmode = "concise"; + if (arg == "-listall") + returnlistmode = "verbose"; + args = args.Where(val => val != arg).ToArray(); + } } + //Console.WriteLine(String.Format("output name: {0}", fname)); + /*foreach (var arg in args) + { + Console.WriteLine(arg); + }*/ //// TESTING @@ -38,24 +69,100 @@ static void Main(string[] args) //}; - if (args.Any() && - args.All(arg => File.Exists(arg) && (arg.EndsWith(".pak", StringComparison.OrdinalIgnoreCase) || arg.EndsWith(".psarc", StringComparison.OrdinalIgnoreCase)))) + if (returnlist) { - foreach (var pakFilePath in args) + // check to see if all the arguments are files ending with .pak, or the arguments specified are folders + if (args.Any() && + (args.All(arg => File.Exists(arg) && (arg.EndsWith(".pak", StringComparison.OrdinalIgnoreCase) || arg.EndsWith(".psarc", StringComparison.OrdinalIgnoreCase))) || + args.All(arg => Directory.Exists(arg)))) { - Functions.Extract(pakFilePath); + // let's get all the sub-directory paks: + List extraMods = new List(); + foreach (string dir in args.Where(dir => Directory.Exists(dir))) + { + IEnumerable files = Directory.EnumerateFiles(dir, "*.pak", SearchOption.AllDirectories); + extraMods.AddRange(files); + } + // and then add them to the args list + extraMods.AddRange(args); + args = extraMods.ToArray(); + + // List of kvp's, with the key being the name of the pak, and the value being a list of all contained files + Dictionary> containedFiles = new Dictionary>(); + // Dictionary with the key being the name of the + Dictionary> sharedFiles = new Dictionary>(); + foreach (var pakFilePath in args) + { + // get the contents of the pak + List pakContents = Functions.ListContents(pakFilePath); + // next, iterate over the current contents of the contained files dict + foreach (KeyValuePair> kvp in containedFiles) + { + // for each pak file, create an enumerable with the list of shared files + IEnumerable intersection = kvp.Value.Intersect(pakContents); + // and for each file that is shared, add the information to the sharedFiles dictionary + foreach (string file in intersection) + { + // if the file that is shared is already a key in the shared file dictionary, then simply add the new name to the list for the key + if (sharedFiles.ContainsKey(file)) + sharedFiles[file].Add(pakFilePath); + // otherwise add a new list with the names of both pak's + else + sharedFiles.Add(file, new List { kvp.Key, pakFilePath }); + } + } + containedFiles.Add(pakFilePath, Functions.ListContents(pakFilePath)); + } + + if (sharedFiles.Count() != 0) + { + Console.WriteLine("\nThe following mods clash:"); + if (returnlistmode == "concise") + { + IEnumerable clashingMods = Enumerable.Empty(); + foreach (KeyValuePair> kvp in sharedFiles) + clashingMods = clashingMods.Union(kvp.Value); + foreach (string mod in clashingMods) + Console.WriteLine(mod); + } + // in this case, write all the files that clash in each mod (they asked for it!!) + else if (returnlistmode == "verbose") + { + foreach (KeyValuePair> kvp in sharedFiles) + { + foreach (string mod in kvp.Value) + { + Console.WriteLine("{0} is in the file {1}", kvp.Key, mod); + } + } + } + } + else + Console.WriteLine("\nNo mods clash!"); + + Console.WriteLine("\nPress ENTER to quit."); + Console.ReadLine(); } } - else if (args.Any() && args.All(arg => File.Exists(arg) || Directory.Exists(arg))) - // A collection of files or folders - { - Functions.Create(args, string.Empty); - } else { - waitForEnter = true; - Console.WriteLine( - "Usage: Pass PAK/PSARC files as arguments to extract (click and drag on to PSArcTool). Pass anything else to create a PAK file."); + if (args.Any() && + args.All(arg => File.Exists(arg) && (arg.EndsWith(".pak", StringComparison.OrdinalIgnoreCase) || arg.EndsWith(".psarc", StringComparison.OrdinalIgnoreCase)))) + { + foreach (var pakFilePath in args) + Functions.Extract(pakFilePath); + + } + else if (args.Any() && args.All(arg => File.Exists(arg) || Directory.Exists(arg))) + // A collection of files or folders + { + Functions.Create(args, string.Empty, fname); + } + else + { + waitForEnter = true; + Console.WriteLine("Usage: Pass PAK/PSARC files as arguments to extract (click and drag on to PSArcTool). Pass anything else to create a PAK file."); + } } }