diff --git a/DepotDownloader/CDRManager.cs b/DepotDownloader/CDRManager.cs index 32e34d1d..1d3c663a 100644 --- a/DepotDownloader/CDRManager.cs +++ b/DepotDownloader/CDRManager.cs @@ -190,7 +190,7 @@ namespace DepotDownloader if ( ver.VersionID == version ) { if ( ver.IsEncryptionKeyAvailable ) - return Util.DecodeHexString( ver.DepotEncryptionKey ); + return Utils.DecodeHexString( ver.DepotEncryptionKey ); break; } } diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index 63de8157..a32eb4f2 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -22,7 +22,7 @@ namespace DepotDownloader private static Steam3Session steam3; private static Steam3Session.Credentials steam3Credentials; - static bool CreateDirectories( int depotId, int depotVersion, out string installDir ) + static bool CreateDirectories( int depotId, uint depotVersion, out string installDir ) { installDir = null; try @@ -193,6 +193,22 @@ namespace DepotDownloader return section_kv; } + static uint GetSteam3AppChangeNumber(int appId) + { + if (steam3 == null || steam3.AppInfo == null) + { + return 0; + } + + SteamApps.AppInfoCallback.AppInfo app; + if (!steam3.AppInfo.TryGetValue((uint)appId, out app)) + { + return 0; + } + + return app.ChangeNumber; + } + static ulong GetSteam3DepotManifest(int depotId, int appId) { if (appId == -1 || !AppIsSteam3(appId)) @@ -260,6 +276,14 @@ namespace DepotDownloader } } + public static void ShutdownSteam3() + { + if (steam3 == null) + return; + + steam3.Disconnect(); + } + private static ContentServerClient.Credentials GetSteam2Credentials(uint appId) { if (steam3 == null || !steam3Credentials.HasSessionToken) @@ -332,7 +356,7 @@ namespace DepotDownloader } } - public static void DownloadDepot(int depotId, int appId, int depotVersion) + public static void DownloadDepot(int depotId, int appId, int depotVersionRequested) { if(steam3 != null && appId > 0) steam3.RequestAppInfo((uint)appId); @@ -346,6 +370,13 @@ namespace DepotDownloader return; } + uint depotVersion = (uint)depotVersionRequested; + + if (appId > 0 && AppIsSteam3(appId)) + { + depotVersion = GetSteam3AppChangeNumber(appId); + } + string installDir; if (!CreateDirectories(depotId, depotVersion, out installDir)) { @@ -355,23 +386,32 @@ namespace DepotDownloader Console.WriteLine("Downloading \"{0}\" version {1} ...", contentName, depotVersion); - ulong manifestID = GetSteam3DepotManifest(depotId, appId); - if (manifestID > 0) + if(steam3 != null) + steam3.RequestAppTicket((uint)depotId); + + if (appId > 0 && AppIsSteam3(appId)) { - DownloadSteam3(depotId, depotVersion, manifestID, installDir); + ulong manifestID = GetSteam3DepotManifest(depotId, appId); + if (manifestID == 0) + { + Console.WriteLine("Depot {0} ({1}) missing Steam3 manifest."); + return; + } + + steam3.RequestDepotKey((uint)depotId); + byte[] depotKey = steam3.DepotKeys[(uint)depotId]; + + DownloadSteam3(depotId, manifestID, depotKey, installDir); } else { // steam2 path - DownloadSteam2(depotId, depotVersion, installDir); + DownloadSteam2(depotId, depotVersionRequested, installDir); } } - private static void DownloadSteam3( int depotId, int depotVersion, ulong depot_manifest, string installDir ) + private static void DownloadSteam3( int depotId, ulong depot_manifest, byte[] depotKey, string installDir ) { - steam3.RequestAppTicket((uint)depotId); - steam3.RequestDepotKey((uint)depotId); - Console.Write("Finding content servers..."); List serverList = steam3.steamClient.GetServersOfType(EServerType.ServerTypeCS); @@ -411,12 +451,9 @@ namespace DepotDownloader return; } - string manifestFile = Path.Combine(installDir, "manifest.bin"); - File.WriteAllBytes(manifestFile, manifest); - DepotManifest depotManifest = new DepotManifest(manifest); - if (!depotManifest.DecryptFilenames(steam3.DepotKeys[(uint)depotId])) + if (!depotManifest.DecryptFilenames(depotKey)) { Console.WriteLine("\nUnable to decrypt manifest for depot {0}", depotId); return; @@ -428,7 +465,6 @@ namespace DepotDownloader 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) @@ -449,20 +485,29 @@ namespace DepotDownloader string dir_path = Path.GetDirectoryName(download_path); - Console.Write("{0:00.00}% Downloading {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); - if (!Directory.Exists(dir_path)) Directory.CreateDirectory(dir_path); + // TODO: non-checksum validation + FileInfo fi = new FileInfo(download_path); + if (fi.Exists && (ulong)fi.Length == file.TotalSize) + { + size_downloaded += file.TotalSize; + Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); + continue; + } + + Console.Write("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); + FileStream fs = File.Create(download_path); fs.SetLength((long)file.TotalSize); foreach (var chunk in file.Chunks) { - string chunkID = Utils.BinToHex(chunk.ChunkID); + string chunkID = Utils.EncodeHexString(chunk.ChunkID); byte[] encrypted_chunk = cdnClient.DownloadDepotChunk(depotId, chunkID); - byte[] chunk_data = cdnClient.ProcessChunk(encrypted_chunk, steam3.DepotKeys[(uint)depotId]); + byte[] chunk_data = cdnClient.ProcessChunk(encrypted_chunk, depotKey); fs.Seek((long)chunk.Offset, SeekOrigin.Begin); fs.Write(chunk_data, 0, chunk_data.Length); @@ -470,7 +515,7 @@ namespace DepotDownloader size_downloaded += chunk.UncompressedLength; Console.CursorLeft = 0; - Console.Write("{0:00.00}", ((float)size_downloaded / (float)complete_download_size) * 100.0f); + Console.Write("{0,6:#00.00}%", ((float)size_downloaded / (float)complete_download_size) * 100.0f); } Console.WriteLine(); @@ -490,7 +535,6 @@ namespace DepotDownloader Console.WriteLine(" Done!"); - string manifestFile = Path.Combine(installDir, "manifest.bin"); string txtManifest = Path.Combine(installDir, "manifest.txt"); ContentServerClient csClient = new ContentServerClient(); @@ -536,9 +580,6 @@ namespace DepotDownloader Console.Write( "Downloading depot manifest..." ); Steam2Manifest manifest = session.DownloadManifest(); - byte[] manifestData = manifest.RawData; - - File.WriteAllBytes( manifestFile, manifestData ); Console.WriteLine( " Done!" ); @@ -588,10 +629,10 @@ namespace DepotDownloader } float perc = ( ( float )x / ( float )manifest.Nodes.Count ) * 100.0f; - Console.WriteLine( " {0:0.00}%\t{1}", perc, downloadPath ); + Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); + // TODO: non-checksum validation FileInfo fi = new FileInfo( downloadPath ); - if ( fi.Exists && fi.Length == dirEntry.SizeOrCount ) continue; diff --git a/DepotDownloader/Program.cs b/DepotDownloader/Program.cs index 57514243..3806426e 100644 --- a/DepotDownloader/Program.cs +++ b/DepotDownloader/Program.cs @@ -203,12 +203,15 @@ namespace DepotDownloader if ( depotVersion == -1 ) { Console.WriteLine( "Error: Unable to find DepotID {0} in the CDR!", currentDepotId ); + ContentDownloader.ShutdownSteam3(); return; } ContentDownloader.DownloadDepot(currentDepotId, -1, depotVersion); } } + + ContentDownloader.ShutdownSteam3(); } static int IndexOfParam( string[] args, string param ) diff --git a/DepotDownloader/Util.cs b/DepotDownloader/Util.cs index 0637721d..d8799f6c 100644 --- a/DepotDownloader/Util.cs +++ b/DepotDownloader/Util.cs @@ -51,20 +51,6 @@ namespace DepotDownloader return false; } - public static byte[] DecodeHexString( string hex ) - { - if ( hex == null ) - return null; - - int chars = hex.Length; - byte[] bytes = new byte[ chars / 2 ]; - - for ( int i = 0 ; i < chars ; i += 2 ) - bytes[ i / 2 ] = Convert.ToByte( hex.Substring(i, 2), 16 ); - - return bytes; - } - public static string ReadPassword() { ConsoleKeyInfo keyInfo;