diff --git a/CASCConsole/Program.cs b/CASCConsole/Program.cs index 0831260..7249ed5 100644 --- a/CASCConsole/Program.cs +++ b/CASCConsole/Program.cs @@ -13,13 +13,15 @@ namespace CASCConsole enum ExtractMode { Pattern, - Listfile + Listfile, + Installfile } class CASCConsoleOptions { public ExtractMode Mode { get; set; } public string ModeParam { get; set; } + public string Region { get; set; } public string DestFolder { get; set; } public LocaleFlags Locale { get; set; } public string Product { get; set; } @@ -27,12 +29,14 @@ class CASCConsoleOptions public string StoragePath { get; set; } public bool OverrideArchive { get; set; } public bool PreferHighResTextures { get; set; } + public string FileTag { get; set; } } internal class CASCConsoleOptionsBinder : BinderBase { private readonly Option modeOption = new Option(new[] { "-m", "--mode" }, "Extraction mode") { IsRequired = true }; private readonly Option modeParamOption = new Option(new[] { "-e", "--eparam" }, "Extraction mode parameter (example: *.* or listfile.csv)") { IsRequired = true }; + private readonly Option region = new Option(new[] { "-r", "--region" }, () => "us", "Region (example: us, eu, cn)"); private readonly Option destOption = new Option(new[] { "-d", "--dest" }, "Destination folder path") { IsRequired = true }; private readonly Option localeOption = new Option(new[] { "-l", "--locale" }, "Product locale") { IsRequired = true }; private readonly Option productOption = new Option(new[] { "-p", "--product" }, "Product uid") { IsRequired = true }; @@ -40,12 +44,13 @@ internal class CASCConsoleOptionsBinder : BinderBase private readonly Option storagePathOption = new Option(new[] { "-s", "--storage" }, () => "", "Local game storage folder"); private readonly Option overrideArchiveOption = new Option(new[] { "-a", "--archive" }, () => false, "Override archive"); private readonly Option preferHighResTexturesOption = new Option(new[] { "-h", "--highres" }, () => false, "High Resolution Textures"); + private readonly Option fileTag = new Option(new[] { "-t", "--tag" }, () => "US", "File tag (example: US, CN, Windows)"); public RootCommand Root { get; } public CASCConsoleOptionsBinder() { - Root = new RootCommand("CASCConsole") { modeOption, modeParamOption, destOption, localeOption, productOption, onlineOption, storagePathOption, overrideArchiveOption, preferHighResTexturesOption }; + Root = new RootCommand("CASCConsole") { modeOption, modeParamOption, region, destOption, localeOption, productOption, onlineOption, storagePathOption, overrideArchiveOption, preferHighResTexturesOption, fileTag }; } protected override CASCConsoleOptions GetBoundValue(BindingContext bindingContext) @@ -56,6 +61,7 @@ protected override CASCConsoleOptions GetBoundValue(BindingContext bindingContex { Mode = parseResult.GetValueForOption(modeOption), ModeParam = parseResult.GetValueForOption(modeParamOption), + Region = parseResult.GetValueForOption(region), DestFolder = parseResult.GetValueForOption(destOption), Locale = parseResult.GetValueForOption(localeOption), Product = parseResult.GetValueForOption(productOption), @@ -63,6 +69,7 @@ protected override CASCConsoleOptions GetBoundValue(BindingContext bindingContex StoragePath = parseResult.GetValueForOption(storagePathOption), OverrideArchive = parseResult.GetValueForOption(overrideArchiveOption), PreferHighResTextures = parseResult.GetValueForOption(preferHighResTexturesOption), + FileTag = parseResult.GetValueForOption(fileTag), }; } } @@ -198,12 +205,12 @@ static void Main(string[] args) var commandsBinder = new CASCConsoleOptionsBinder(); commandsBinder.Root.SetHandler((CASCConsoleOptions options) => { - Extract(options.Mode, options.ModeParam, options.DestFolder, options.Locale, options.Product, options.Online, options.StoragePath, options.OverrideArchive, options.PreferHighResTextures); + Extract(options.Mode, options.ModeParam, options.Region, options.DestFolder, options.Locale, options.Product, options.Online, options.StoragePath, options.OverrideArchive, options.PreferHighResTextures, options.FileTag); }, commandsBinder); commandsBinder.Root.Invoke(args); } - private static void Extract(ExtractMode mode, string modeParam, string destFolder, LocaleFlags locale, string product, bool online, string storagePath, bool overrideArchive, bool preferHighResTextures) + private static void Extract(ExtractMode mode, string modeParam, string region, string destFolder, LocaleFlags locale, string product, bool online, string storagePath, bool overrideArchive, bool preferHighResTextures, string fileTag) { DateTime startTime = DateTime.Now; @@ -212,6 +219,7 @@ private static void Extract(ExtractMode mode, string modeParam, string destFolde Console.WriteLine("Extract params:"); Console.WriteLine(" Mode: {0}", mode); Console.WriteLine(" Mode Param: {0}", modeParam); + Console.WriteLine(" Region: {0}", region); Console.WriteLine(" Destination: {0}", destFolder); Console.WriteLine(" LocaleFlags: {0}", locale); Console.WriteLine(" Product: {0}", product); @@ -219,6 +227,7 @@ private static void Extract(ExtractMode mode, string modeParam, string destFolde Console.WriteLine(" Storage Path: {0}", storagePath); Console.WriteLine(" OverrideArchive: {0}", overrideArchive); Console.WriteLine(" PreferHighResTextures: {0}", preferHighResTextures); + Console.WriteLine(" Tag: {0}", fileTag); Console.WriteLine("Loading..."); @@ -228,7 +237,7 @@ private static void Extract(ExtractMode mode, string modeParam, string destFolde CASCConfig.LoadFlags |= LoadFlags.Install; CASCConfig config = online - ? CASCConfig.LoadOnlineStorageConfig(product, "us") + ? CASCConfig.LoadOnlineStorageConfig(product, region) : CASCConfig.LoadLocalStorageConfig(storagePath, product); CASCHandler cascHandler = CASCHandler.OpenStorage(config, bgLoader); @@ -268,6 +277,24 @@ private static void Extract(ExtractMode mode, string modeParam, string destFolde ExtractFile(cascHandler, 0, file, destFolder); } } + else if (mode == ExtractMode.Installfile) + { + Wildcard wildcard = new Wildcard(modeParam, true, RegexOptions.IgnoreCase); + + var installFiles = cascHandler.Install.GetEntriesByTag(fileTag); + var build = cascHandler.Config.BuildName; + int numFiles = installFiles.Count(); + + foreach (var file in installFiles) + { + if (cascHandler.Encoding.GetEntry(file.MD5, out EncodingEntry enc) && wildcard.IsMatch(file.Name)) + { + cascHandler.SaveFileTo(enc.Keys[0], destFolder, file.Name); + + Console.WriteLine("Extracting '{0}'...", file.Name); + } + } + } Console.WriteLine("Extracted.");