diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index cb9eb063..9f8a9b19 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -24,6 +24,53 @@ namespace DepotDownloader private static Steam3Session steam3; private static Steam3Session.Credentials steam3Credentials; + private static IPEndPoint lastSteam2ContentServer; + + private abstract class IDepotDownloadInfo + { + public int id { get; protected set; } + public string installDir { get; protected set; } + public string contentName { get; protected set; } + + public abstract DownloadSource GetDownloadType(); + } + + private sealed class DepotDownloadInfo2 : IDepotDownloadInfo + { + public int version { get; private set; } + + public IPEndPoint[] contentServers = null; + public Steam2Manifest manifest = null; + public List NodesToDownload = new List(); + public byte[] cryptKey = null; + + public override DownloadSource GetDownloadType() { return DownloadSource.Steam2; } + + public DepotDownloadInfo2(int id, int version, string installDir, string contentName) + { + this.id = id; + this.version = version; + this.installDir = installDir; + this.contentName = contentName; + } + } + + private sealed class DepotDownloadInfo3 : IDepotDownloadInfo + { + public ulong manifestId { get; private set; } + public byte[] depotKey; + + public override DownloadSource GetDownloadType() { return DownloadSource.Steam3; } + + public DepotDownloadInfo3(int depotid, ulong manifestId, string installDir, string contentName) + { + this.id = depotid; + this.manifestId = manifestId; + this.installDir = installDir; + this.contentName = contentName; + } + } + static bool CreateDirectories( int depotId, uint depotVersion, out string installDir ) { installDir = null; @@ -404,6 +451,9 @@ namespace DepotDownloader return; } + var infos2 = new List(); + var infos3 = new List(); + foreach (var depot in depotIDs) { int depotVersion = 0; @@ -419,11 +469,74 @@ namespace DepotDownloader } } - DownloadDepot(depot, depotVersion, appId); + IDepotDownloadInfo info = GetDepotInfo(depot, depotVersion, appId); + if (info != null) + { + if (info.GetDownloadType() == DownloadSource.Steam2) + infos2.Add((DepotDownloadInfo2)info); + else if (info.GetDownloadType() == DownloadSource.Steam3) + infos3.Add((DepotDownloadInfo3)info); + } + } + + if( infos2.Count() > 0 ) + DownloadSteam2( infos2 ); + + if( infos3.Count() > 0 ) + DownloadSteam3( infos3 ); + } + + public static void DownloadDepotsForGame(string game) + { + var infos2 = new List(); + var infos3 = new List(); + List depotIDs = CDRManager.GetDepotIDsForGameserver(game, ContentDownloader.Config.DownloadAllPlatforms); + foreach (var depot in depotIDs) + { + int depotVersion = CDRManager.GetLatestDepotVersion(depot, ContentDownloader.Config.PreferBetaVersions); + if (depotVersion == -1) + { + Console.WriteLine("Error: Unable to find DepotID {0} in the CDR!", depot); + ContentDownloader.ShutdownSteam3(); + continue; + } + + IDepotDownloadInfo info = GetDepotInfo(depot, depotVersion, 0); + if (info.GetDownloadType() == DownloadSource.Steam2) + { + infos2.Add((DepotDownloadInfo2)info); + } + else if (info.GetDownloadType() == DownloadSource.Steam3) + { + infos3.Add((DepotDownloadInfo3)info); + } + } + + if (infos2.Count() > 0) + DownloadSteam2(infos2); + + if (infos3.Count() > 0) + DownloadSteam3(infos3); + } + + public static void DownloadDepot(int depotId, int depotVersion, int appId = 0) + { + IDepotDownloadInfo info = GetDepotInfo(depotId, depotVersion, appId); + if (info.GetDownloadType() == DownloadSource.Steam2) + { + var infos = new List(); + infos.Add((DepotDownloadInfo2)info); + DownloadSteam2(infos); + } + else if (info.GetDownloadType() == DownloadSource.Steam3) + { + var infos = new List(); + infos.Add((DepotDownloadInfo3)info); + DownloadSteam3(infos); } } - public static void DownloadDepot(int depotId, int depotVersionRequested, int appId = 0 ) + static IDepotDownloadInfo GetDepotInfo(int depotId, int depotVersion, int appId) { if(steam3 != null && appId > 0) steam3.RequestAppInfo((uint)appId); @@ -434,25 +547,26 @@ namespace DepotDownloader { Console.WriteLine("Depot {0} ({1}) is not available from this account.", depotId, contentName); - return; + return null; } DownloadSource source = GetAppDownloadSource(appId); - uint depotVersion = (uint)depotVersionRequested; + + uint uVersion = (uint)depotVersion; if (source == DownloadSource.Steam3) { - depotVersion = GetSteam3AppChangeNumber(appId); + uVersion = GetSteam3AppChangeNumber(appId); } string installDir; - if (!CreateDirectories(depotId, depotVersion, out installDir)) + if (!CreateDirectories(depotId, uVersion, out installDir)) { Console.WriteLine("Error: Unable to create install directories!"); - return; + return null; } - Console.WriteLine("Downloading \"{0}\" version {1} ...", contentName, depotVersion); + Console.WriteLine("Downloading \"{0}\" version {1} ...", contentName, uVersion); if(steam3 != null) steam3.RequestAppTicket((uint)depotId); @@ -463,213 +577,224 @@ namespace DepotDownloader if (manifestID == 0) { Console.WriteLine("Depot {0} ({1}) missing public subsection or manifest section.", depotId, contentName); - return; + return null; } steam3.RequestDepotKey( ( uint )depotId, ( uint )appId ); byte[] depotKey = steam3.DepotKeys[(uint)depotId]; - DownloadSteam3(depotId, manifestID, depotKey, installDir); + var info = new DepotDownloadInfo3( depotId, manifestID, installDir, contentName ); + info.depotKey = depotKey; + return info; } else { // steam2 path - DownloadSteam2(depotId, depotVersionRequested, installDir); + var info = new DepotDownloadInfo2(depotId, depotVersion, installDir, contentName); + return info; } } - private static void DownloadSteam3( int depotId, ulong depot_manifest, byte[] depotKey, string installDir ) + private static void DownloadSteam3( List depots ) { - Console.Write("Finding content servers..."); + foreach (var depot in depots) + { + int depotId = depot.id; + ulong depot_manifest = depot.manifestId; + byte[] depotKey = depot.depotKey; + string installDir = depot.installDir; - List serverList = steam3.steamClient.GetServersOfType(EServerType.CS); + Console.WriteLine("Downloading depot {0} - {1}", depot.id, depot.contentName); + Console.Write("Finding content servers..."); - List cdnServers = null; - int tries = 0, counterDeferred = 0; + List serverList = steam3.steamClient.GetServersOfType(EServerType.CS); - for(int i = 0; ; i++ ) - { - IPEndPoint endpoint = serverList[i % serverList.Count]; + List cdnServers = null; + int counterDeferred = 0; - cdnServers = CDNClient.FetchServerList(new CDNClient.ClientEndPoint(endpoint.Address.ToString(), endpoint.Port), Config.CellID); + for (int i = 0; ; i++) + { + IPEndPoint endpoint = serverList[i % serverList.Count]; - if (cdnServers == null) counterDeferred++; + cdnServers = CDNClient.FetchServerList(new CDNClient.ClientEndPoint(endpoint.Address.ToString(), endpoint.Port), Config.CellID); - if (cdnServers != null && cdnServers.Count((ep) => { return ep.Type == "CS"; }) > 0) - break; + if (cdnServers == null) counterDeferred++; - if (((i+1) % serverList.Count) == 0) - { - if (++tries > MAX_CONNECT_RETRIES) + if (cdnServers != null && cdnServers.Count((ep) => { return ep.Type == "CS"; }) > 0) + break; + + if (((i + 1) % serverList.Count) == 0) { - Console.WriteLine("\nGiving up finding Steam3 content server."); + Console.WriteLine("Unable to find any Steam3 content servers"); return; } - - Console.Write("\nSearching for content servers... (deferred: {0})", counterDeferred); - counterDeferred = 0; - Thread.Sleep(1000); } - } - - if (cdnServers == null || cdnServers.Count == 0) - { - Console.WriteLine("Unable to find any Steam3 content servers"); - return; - } - Console.WriteLine(" Done!"); - Console.Write("Downloading depot manifest..."); + Console.WriteLine(" Done!"); + Console.Write("Downloading depot manifest..."); - List cdnEndpoints = cdnServers.Where((ep) => { return ep.Type == "CDN"; }).ToList(); - List csEndpoints = cdnServers.Where((ep) => { return ep.Type == "CS"; }).ToList(); + List cdnEndpoints = cdnServers.Where((ep) => { return ep.Type == "CDN"; }).ToList(); + List csEndpoints = cdnServers.Where((ep) => { return ep.Type == "CS"; }).ToList(); + List cdnClients = new List(); - List cdnClients = new List(); + foreach (var server in csEndpoints) + { + CDNClient client = new CDNClient(server, steam3.AppTickets[(uint)depotId]); - foreach (var server in csEndpoints) - { - CDNClient client = new CDNClient(server, steam3.AppTickets[(uint)depotId]); + if (client.Connect()) + { + cdnClients.Add(client); - if (client.Connect()) + if (cdnClients.Count >= NUM_STEAM3_CONNECTIONS) + break; + } + } + if (cdnClients.Count == 0) { - cdnClients.Add(client); - - if (cdnClients.Count >= NUM_STEAM3_CONNECTIONS) - break; + Console.WriteLine("\nCould not initialize connection with CDN."); + return; } - } - - if (cdnClients.Count == 0) - { - Console.WriteLine("\nCould not initialize connection with CDN."); - return; - } - DepotManifest depotManifest = cdnClients[0].DownloadDepotManifest( depotId, depot_manifest ); + DepotManifest depotManifest = cdnClients[0].DownloadDepotManifest( depotId, depot_manifest ); - if ( depotManifest == null ) - { - // TODO: check for 401s - for (int i = 1; i < cdnClients.Count && depotManifest == null; i++) + if ( depotManifest == null ) { - depotManifest = cdnClients[i].DownloadDepotManifest( depotId, depot_manifest ); + // TODO: check for 401s + for (int i = 1; i < cdnClients.Count && depotManifest == null; i++) + { + depotManifest = cdnClients[i].DownloadDepotManifest( depotId, depot_manifest ); + } + + if (depotManifest == null) + { + Console.WriteLine("\nUnable to download manifest {0} for depot {1}", depot_manifest, depotId); + return; + } } - if (depotManifest == null) + if (!depotManifest.DecryptFilenames(depotKey)) { - Console.WriteLine("\nUnable to download manifest {0} for depot {1}", depot_manifest, depotId); + Console.WriteLine("\nUnable to decrypt manifest for depot {0}", depotId); return; } - } - - if (!depotManifest.DecryptFilenames(depotKey)) - { - Console.WriteLine("\nUnable to decrypt manifest for depot {0}", depotId); - return; - } - Console.WriteLine(" Done!"); + Console.WriteLine(" Done!"); - ulong complete_download_size = 0; - ulong size_downloaded = 0; + ulong complete_download_size = 0; + ulong size_downloaded = 0; - depotManifest.Files.RemoveAll((x) => !TestIsFileIncluded(x.FileName)); - depotManifest.Files.Sort((x, y) => { return x.FileName.CompareTo(y.FileName); }); - - foreach (var file in depotManifest.Files) - { - complete_download_size += file.TotalSize; - } + depotManifest.Files.RemoveAll((x) => !TestIsFileIncluded(x.FileName)); + depotManifest.Files.Sort((x, y) => { return x.FileName.CompareTo(y.FileName); }); - foreach (var file in depotManifest.Files) - { - string download_path = Path.Combine(installDir, file.FileName); - - if (file.Flags.HasFlag(EDepotFileFlag.Directory)) + foreach (var file in depotManifest.Files) { - if (!Directory.Exists(download_path)) - Directory.CreateDirectory(download_path); - continue; + complete_download_size += file.TotalSize; } - string dir_path = Path.GetDirectoryName(download_path); - - if (!Directory.Exists(dir_path)) - Directory.CreateDirectory(dir_path); - - FileStream fs; - DepotManifest.ChunkData[] neededChunks; - FileInfo fi = new FileInfo(download_path); - if (!fi.Exists) + foreach (var file in depotManifest.Files) { - // create new file. need all chunks - fs = File.Create(download_path); - neededChunks = file.Chunks.ToArray(); - } - else - { - // open existing - fs = File.Open(download_path, FileMode.Open); - if ((ulong)fi.Length != file.TotalSize) - { - fs.SetLength((long)file.TotalSize); + string download_path = Path.Combine(installDir, file.FileName); + + if (file.Flags.HasFlag(EDepotFileFlag.Directory)) + { + if (!Directory.Exists(download_path)) + Directory.CreateDirectory(download_path); + continue; } - // find which chunks we need, in order so that we aren't seeking every which way - neededChunks = Util.ValidateSteam3FileChecksums(fs, file.Chunks.OrderBy(x => x.Offset).ToArray()); + string dir_path = Path.GetDirectoryName(download_path); + + if (!Directory.Exists(dir_path)) + Directory.CreateDirectory(dir_path); - if (neededChunks.Count() == 0) + FileStream fs; + DepotManifest.ChunkData[] neededChunks; + FileInfo fi = new FileInfo(download_path); + if (!fi.Exists) { - size_downloaded += file.TotalSize; - Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); - continue; + // create new file. need all chunks + fs = File.Create(download_path); + neededChunks = file.Chunks.ToArray(); } else { - size_downloaded += (file.TotalSize - (ulong)neededChunks.Select(x => (int)x.UncompressedLength).Sum()); + // open existing + fs = File.Open(download_path, FileMode.Open); + if ((ulong)fi.Length != file.TotalSize) + { + fs.SetLength((long)file.TotalSize); + } + + // find which chunks we need, in order so that we aren't seeking every which way + neededChunks = Util.ValidateSteam3FileChecksums(fs, file.Chunks.OrderBy(x => x.Offset).ToArray()); + + if (neededChunks.Count() == 0) + { + size_downloaded += file.TotalSize; + Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); + continue; + } + else + { + size_downloaded += (file.TotalSize - (ulong)neededChunks.Select(x => (int)x.UncompressedLength).Sum()); + } } - } - Console.Write("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); + Console.Write("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); - foreach (var chunk in neededChunks) - { - string chunkID = EncodeHexString(chunk.ChunkID); - - byte[] encrypted_chunk = cdnClients[0].DownloadDepotChunk(depotId, chunkID); - - if (encrypted_chunk == null) + foreach (var chunk in neededChunks) { - for (int i = 1; i < cdnClients.Count && encrypted_chunk == null; i++) - { - encrypted_chunk = cdnClients[i].DownloadDepotChunk(depotId, chunkID); - } + string chunkID = EncodeHexString(chunk.ChunkID); + + byte[] encrypted_chunk = cdnClients[0].DownloadDepotChunk(depotId, chunkID); if (encrypted_chunk == null) { - Console.WriteLine("Unable to download chunk id {0} for depot {1}", chunkID, depotId); - return; + for (int i = 1; i < cdnClients.Count && encrypted_chunk == null; i++) + { + encrypted_chunk = cdnClients[i].DownloadDepotChunk(depotId, chunkID); + } + + if (encrypted_chunk == null) + { + Console.WriteLine("Unable to download chunk id {0} for depot {1}", chunkID, depotId); + return; + } } - } - byte[] chunk_data = CDNClient.ProcessChunk(encrypted_chunk, depotKey); + byte[] chunk_data = CDNClient.ProcessChunk(encrypted_chunk, depotKey); - fs.Seek((long)chunk.Offset, SeekOrigin.Begin); - fs.Write(chunk_data, 0, chunk_data.Length); + fs.Seek((long)chunk.Offset, SeekOrigin.Begin); + fs.Write(chunk_data, 0, chunk_data.Length); - size_downloaded += chunk.UncompressedLength; + size_downloaded += chunk.UncompressedLength; - Console.CursorLeft = 0; - Console.Write("{0,6:#00.00}%", ((float)size_downloaded / (float)complete_download_size) * 100.0f); - } + Console.CursorLeft = 0; + Console.Write("{0,6:#00.00}%", ((float)size_downloaded / (float)complete_download_size) * 100.0f); + } - Console.WriteLine(); + Console.WriteLine(); + } } } private static ContentServerClient.StorageSession GetSteam2StorageSession(IPEndPoint [] contentServers, ContentServerClient csClient, int depotId, int depotVersion) { ContentServerClient.StorageSession session = null; + if (csClient.IsConnected && contentServers.Contains(lastSteam2ContentServer)) + { + try + { + session = csClient.OpenStorage( (uint)depotId, (uint)depotVersion, (uint)Config.CellID, null, false ); + + return session; + } + catch ( Steam2Exception ) + { + csClient.Disconnect(); + } + } + int tries = 0; int counterSocket = 0, counterSteam2 = 0; for (int i = 0; ; i++) @@ -679,7 +804,8 @@ namespace DepotDownloader try { csClient.Connect( endpoint ); - session = csClient.OpenStorage( (uint)depotId, (uint)depotVersion, (uint)Config.CellID, GetSteam2Credentials( (uint)depotId ) ); + session = csClient.OpenStorage( (uint)depotId, (uint)depotVersion, (uint)Config.CellID, GetSteam2Credentials( (uint)depotId ), true ); + lastSteam2ContentServer = endpoint; break; } catch ( SocketException ) @@ -708,135 +834,146 @@ namespace DepotDownloader } return session; } - private static void DownloadSteam2( int depotId, int depotVersion, string installDir ) + private static void DownloadSteam2( List depots ) { - Console.Write("Finding content servers..."); - IPEndPoint[] contentServers = GetStorageServer(depotId, depotVersion, Config.CellID); + Console.WriteLine("Found depots:"); + foreach (var depot in depots) + { + Console.WriteLine(" - {0}\t{1}", depot.id, depot.contentName); + } - if (contentServers == null || contentServers.Length == 0) + Console.Write("Finding content servers..."); + foreach( var depot in depots ) { - Console.WriteLine("\nError: Unable to find any Steam2 content servers for depot {0}, version {1}", depotId, depotVersion); - return; + depot.contentServers = GetStorageServer(depot.id, depot.version, Config.CellID); + if (depot.contentServers == null || depot.contentServers.Length == 0) + { + Console.WriteLine("\nError: Unable to find any Steam2 content servers for depot {0}, version {1}", depot.id, depot.version); + return; + } } Console.WriteLine(" Done!"); - Console.Write("Downloading depot manifest..."); - string txtManifest = Path.Combine(installDir, "manifest.txt"); + if (!Config.DownloadManifestOnly) + Console.WriteLine("Building list of files to download and checking existing files..."); ContentServerClient csClient = new ContentServerClient(); csClient.ConnectionTimeout = TimeSpan.FromSeconds(STEAM2_CONNECT_TIMEOUT_SECONDS); - ContentServerClient.StorageSession session = GetSteam2StorageSession(contentServers, csClient, depotId, depotVersion); - if(session == null) - return; + ContentServerClient.StorageSession session; - Steam2Manifest manifest = null; - Steam2ChecksumData checksums = null; - List NodesToDownload = new List(); - StringBuilder manifestBuilder = new StringBuilder(); - byte[] cryptKey = CDRManager.GetDepotEncryptionKey( depotId, depotVersion ); - string[] excludeList = null; - using ( session ) + foreach (var depot in depots) { - manifest = session.DownloadManifest(); + session = GetSteam2StorageSession(depot.contentServers, csClient, depot.id, depot.version); + if (session == null) + continue; - Console.WriteLine( " Done!" ); + Console.Write(String.Format("Downloading manifest for depot {0}...", depot.id)); - if(!Config.DownloadManifestOnly) - { - // Skip downloading checksums if we're only interested in manifests. - Console.Write("Downloading depot checksums..."); + string txtManifest = Path.Combine(depot.installDir, "manifest.txt"); + Steam2ChecksumData checksums = null; + StringBuilder manifestBuilder = new StringBuilder(); + string[] excludeList = null; - checksums = session.DownloadChecksums(); + depot.cryptKey = CDRManager.GetDepotEncryptionKey(depot.id, depot.version); + depot.manifest = session.DownloadManifest(); - Console.WriteLine(" Done!"); - } + Console.WriteLine(" Done!"); - if ( Config.UsingExclusionList ) - excludeList = GetExcludeList( session, manifest ); - } - csClient.Disconnect(); + if (Config.UsingExclusionList) + excludeList = GetExcludeList(session, depot.manifest); - if(!Config.DownloadManifestOnly) - Console.WriteLine("Building list of files to download and checking existing files..."); - // Build a list of files that need downloading. - for ( int x = 0 ; x < manifest.Nodes.Count ; ++x ) - { - var dirEntry = manifest.Nodes[ x ]; - string downloadPath = Path.Combine( installDir, dirEntry.FullName.ToLower() ); - if ( Config.DownloadManifestOnly ) + // Build a list of files that need downloading. + for (int x = 0; x < depot.manifest.Nodes.Count; ++x) { - if ( dirEntry.FileID == -1 ) - continue; + var dirEntry = depot.manifest.Nodes[x]; + string downloadPath = Path.Combine(depot.installDir, dirEntry.FullName.ToLower()); + if (Config.DownloadManifestOnly) + { + if (dirEntry.FileID == -1) + continue; - manifestBuilder.Append( string.Format( "{0}\n", dirEntry.FullName ) ); - continue; - } - if (Config.UsingExclusionList && IsFileExcluded(dirEntry.FullName, excludeList)) - continue; + manifestBuilder.Append(string.Format("{0}\n", dirEntry.FullName)); + continue; + } + if (Config.UsingExclusionList && IsFileExcluded(dirEntry.FullName, excludeList)) + continue; - if (!TestIsFileIncluded(dirEntry.FullName)) - continue; + if (!TestIsFileIncluded(dirEntry.FullName)) + continue; - string path = Path.GetDirectoryName(downloadPath); + string path = Path.GetDirectoryName(downloadPath); - if (path != "" && !Directory.Exists(path)) - Directory.CreateDirectory(path); + if (path != "" && !Directory.Exists(path)) + Directory.CreateDirectory(path); - if ( dirEntry.FileID == -1 ) - { - if ( !Directory.Exists( downloadPath ) ) + if ( dirEntry.FileID == -1 ) { - // this is a directory, so lets just create it - Directory.CreateDirectory( downloadPath ); + if ( !Directory.Exists( downloadPath ) ) + { + // this is a directory, so lets just create it + Directory.CreateDirectory( downloadPath ); + } + + continue; } - continue; - } + if (checksums == null) + { + // Skip downloading checksums if we're only interested in manifests. + Console.Write(String.Format("Downloading checksums for depot {0}...", depot.id)); - FileInfo fi = new FileInfo( downloadPath ); - if (fi.Exists) - { - float perc = ( ( float )x / ( float )manifest.Nodes.Count ) * 100.0f; - Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); - // Similar file, let's check checksums - if(fi.Length == dirEntry.SizeOrCount && - Util.ValidateSteam2FileChecksums(fi, checksums.GetFileChecksums(dirEntry.FileID))) + checksums = session.DownloadChecksums(); + + Console.WriteLine(" Done!"); + } + + FileInfo fi = new FileInfo(downloadPath); + if (fi.Exists) { - // checksums OK - continue; + float perc = ((float)x / (float)depot.manifest.Nodes.Count) * 100.0f; + Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); + // Similar file, let's check checksums + if (fi.Length == dirEntry.SizeOrCount && + Util.ValidateSteam2FileChecksums(fi, checksums.GetFileChecksums(dirEntry.FileID))) + { + // checksums OK + continue; + } + // Unlink the current file before we download a new one. + // This will keep symbolic/hard link targets from being overwritten. + fi.Delete(); } - // Unlink the current file before we download a new one. - // This will keep symbolic/hard link targets from being overwritten. - fi.Delete(); + depot.NodesToDownload.Add(x); } - NodesToDownload.Add(x); - } - if ( Config.DownloadManifestOnly ) - { - File.WriteAllText( txtManifest, manifestBuilder.ToString() ); + if (Config.DownloadManifestOnly) + { + File.WriteAllText(txtManifest, manifestBuilder.ToString()); return; + } } - - - session = GetSteam2StorageSession(contentServers, csClient, depotId, depotVersion); - if(session == null) - return; - - using ( session ) + + Console.WriteLine("Downloading selected files."); + foreach( var depot in depots ) { - Console.WriteLine("Downloading selected files."); - for ( int x = 0 ; x < NodesToDownload.Count ; ++x ) + if (depot.NodesToDownload.Count == 0) + continue; + + session = GetSteam2StorageSession(depot.contentServers, csClient, depot.id, depot.version); + if(session == null) + continue; + + for ( int x = 0 ; x < depot.NodesToDownload.Count ; ++x ) { - var dirEntry = manifest.Nodes[ NodesToDownload[ x ] ]; - string downloadPath = Path.Combine( installDir, dirEntry.FullName.ToLower() ); + var dirEntry = depot.manifest.Nodes[ depot.NodesToDownload[ x ] ]; + string downloadPath = Path.Combine( depot.installDir, dirEntry.FullName.ToLower() ); - float perc = ( ( float )x / ( float )NodesToDownload.Count ) * 100.0f; + float perc = ( ( float )x / ( float )depot.NodesToDownload.Count ) * 100.0f; Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); - var file = session.DownloadFile( dirEntry, ContentServerClient.StorageSession.DownloadPriority.High, cryptKey ); + var file = session.DownloadFile( dirEntry, ContentServerClient.StorageSession.DownloadPriority.High, depot.cryptKey ); File.WriteAllBytes( downloadPath, file ); } }