diff --git a/Projects/DepotDownloader/DepotDownloader/CDRManager.cs b/Projects/DepotDownloader/DepotDownloader/CDRManager.cs index 9a9e1163..32e34d1d 100644 --- a/Projects/DepotDownloader/DepotDownloader/CDRManager.cs +++ b/Projects/DepotDownloader/DepotDownloader/CDRManager.cs @@ -12,6 +12,9 @@ namespace DepotDownloader { [BlobField( FieldKey = CDRFields.eFieldApplicationsRecord, Depth = 1, Complex = true )] public List Apps { get; set; } + + [BlobField( FieldKey = CDRFields.eFieldSubscriptionsRecord, Depth = 1, Complex = true )] + public List Subs { get; set; } } class App @@ -33,6 +36,18 @@ namespace DepotDownloader [BlobField( FieldKey = CDRAppRecordFields.eFieldUserDefinedRecord, Depth = 1 )] public Dictionary UserDefined { get; private set; } + + [BlobField( FieldKey = CDRAppRecordFields.eFieldBetaVersionId, Depth = 1 )] + public int BetaVersion { get; set; } + } + + class Sub + { + [BlobField( FieldKey = CDRSubRecordFields.eFieldSubId, Depth = 1 )] + public int SubID { get; set; } + + [BlobField( FieldKey = CDRSubRecordFields.eFieldAppIdsRecord, Depth = 1 )] + public List AppIDs { get; private set; } } class AppVersion @@ -121,6 +136,11 @@ namespace DepotDownloader return cdrObj.Apps.Find( ( app ) => app.AppID == appID ); } + static Sub GetSubBlob( int subID ) + { + return cdrObj.Subs.Find( ( sub ) => sub.SubID == subID ); + } + public static string GetDepotName( int depotId ) { // Match hardcoded names from hldsupdatetool for certain HL1 depots @@ -141,7 +161,7 @@ namespace DepotDownloader return app.Name; } - public static int GetLatestDepotVersion( int depotId ) + public static int GetLatestDepotVersion( int depotId, bool beta ) { App app = GetAppBlob( depotId ); @@ -150,6 +170,9 @@ namespace DepotDownloader return -1; } + if ( beta && app.BetaVersion > app.CurrentVersion ) + return app.BetaVersion; + return app.CurrentVersion; } @@ -352,6 +375,16 @@ namespace DepotDownloader Console.WriteLine( "\t\"{0}\"", game ); } + public static bool SubHasDepot( int subId, int depotId ) + { + Sub sub = GetSubBlob( subId ); + + if ( sub == null ) + return false; + + return sub.AppIDs.Contains( depotId ); + } + static byte[] GetCdr() { try diff --git a/Projects/DepotDownloader/DepotDownloader/ContentDownloader.cs b/Projects/DepotDownloader/DepotDownloader/ContentDownloader.cs index ffb408e8..0bcacd8f 100644 --- a/Projects/DepotDownloader/DepotDownloader/ContentDownloader.cs +++ b/Projects/DepotDownloader/DepotDownloader/ContentDownloader.cs @@ -14,6 +14,7 @@ namespace DepotDownloader static class ContentDownloader { const string DEFAULT_DIR = "depots"; + const int MAX_STORAGE_RETRIES = 500; static Steam3Session steam3; @@ -108,6 +109,20 @@ namespace DepotDownloader return false; } + static bool AccountHasAccess( int depotId ) + { + if ( steam3 == null || steam3.Licenses == null ) + return CDRManager.SubHasDepot( 0, depotId ); + + foreach ( var license in steam3.Licenses ) + { + if ( CDRManager.SubHasDepot( ( int )license.PackageID, depotId ) ) + return true; + } + + return false; + } + public static void Download( int depotId, int depotVersion, int cellId, string username, string password, bool onlyManifest, bool gameServer, bool exclude, string installDir, string[] fileList ) { if ( !CreateDirectories( depotId, depotVersion, ref installDir ) ) @@ -135,22 +150,10 @@ namespace DepotDownloader credentials = GetCredentials( ( uint )depotId, username, password ); } - string manifestFile = Path.Combine( installDir, "manifest.bin" ); - string txtManifest = Path.Combine( installDir, "manifest.txt" ); - - ContentServerClient csClient = new ContentServerClient(); - - csClient.Connect( contentServer ); - - - ContentServerClient.StorageSession session = null; - try + if ( !AccountHasAccess( depotId ) ) { - session = csClient.OpenStorage( ( uint )depotId, ( uint )depotVersion, ( uint )cellId, credentials ); - } - catch ( Steam2Exception ex ) - { - Console.WriteLine( "Unable to open storage: " + ex.Message ); + string contentName = CDRManager.GetDepotName( depotId ); + Console.WriteLine( "Depot {0} ({1}) is not available from this account.", depotId, contentName ); if ( steam3 != null ) steam3.Disconnect(); @@ -158,6 +161,37 @@ namespace DepotDownloader return; } + string manifestFile = Path.Combine( installDir, "manifest.bin" ); + string txtManifest = Path.Combine( installDir, "manifest.txt" ); + + ContentServerClient csClient = new ContentServerClient(); + + ContentServerClient.StorageSession session = null; + int retryCount = 0; + + while ( session == null ) + { + try + { + csClient.Connect( contentServer ); + session = csClient.OpenStorage( ( uint )depotId, ( uint )depotVersion, ( uint )cellId, credentials ); + } + catch ( Steam2Exception ex ) + { + csClient.Disconnect(); + retryCount++; + + if ( retryCount > MAX_STORAGE_RETRIES ) + { + Console.WriteLine( "Unable to open storage: " + ex.Message ); + + if (steam3 != null) + steam3.Disconnect(); + return; + } + } + } + using ( session ) { diff --git a/Projects/DepotDownloader/DepotDownloader/Program.cs b/Projects/DepotDownloader/DepotDownloader/Program.cs index 6d7fe48d..a74b4fd0 100644 --- a/Projects/DepotDownloader/DepotDownloader/Program.cs +++ b/Projects/DepotDownloader/DepotDownloader/Program.cs @@ -59,10 +59,11 @@ namespace DepotDownloader } int depotVersion = GetIntParameter( args, "-version" ); + bool bBeta = HasParameter( args, "-beta" ); if ( !bGameserver && !bApp && depotVersion == -1 ) { - int latestVer = CDRManager.GetLatestDepotVersion( depotId ); + int latestVer = CDRManager.GetLatestDepotVersion( depotId, bBeta ); if ( latestVer == -1 ) { @@ -134,7 +135,7 @@ namespace DepotDownloader foreach ( int currentDepotId in depotIDs ) { - depotVersion = CDRManager.GetLatestDepotVersion( currentDepotId ); + depotVersion = CDRManager.GetLatestDepotVersion( currentDepotId, bBeta ); if ( depotVersion == -1 ) { Console.WriteLine( "Error: Unable to find DepotID {0} in the CDR!", currentDepotId ); @@ -208,7 +209,8 @@ namespace DepotDownloader Console.WriteLine( "\t-dir installdir\t\t\t- the directory in which to place downloaded files." ); Console.WriteLine( "\t-filelist filename.txt\t\t- a list of files to download (from the manifest). Can optionally use regex to download only certain files." ); Console.WriteLine( "\t-no-exclude\t\t\t- don't exclude any files when downloading depots with the -game parameter." ); - Console.WriteLine( "\t-all-platforms\t\t\t- downloads all platform-specific depots when -game or -app is used.\n" ); + Console.WriteLine( "\t-all-platforms\t\t\t- downloads all platform-specific depots when -game or -app is used." ); + Console.WriteLine( "\t-beta\t\t\t\t- download beta version of depots if available." ); } } } diff --git a/Projects/DepotDownloader/DepotDownloader/Steam3Session.cs b/Projects/DepotDownloader/DepotDownloader/Steam3Session.cs index c3dd5a96..c94ca21c 100644 --- a/Projects/DepotDownloader/DepotDownloader/Steam3Session.cs +++ b/Projects/DepotDownloader/DepotDownloader/Steam3Session.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using SteamKit2; using System.Threading; +using System.Collections.ObjectModel; namespace DepotDownloader { @@ -18,6 +19,12 @@ namespace DepotDownloader public byte[] AppTicket { get; set; } } + public ReadOnlyCollection Licenses + { + get; + private set; + } + SteamClient steamClient; SteamUser steamUser; @@ -90,7 +97,7 @@ namespace DepotDownloader if ( diff > STEAM3_TIMEOUT && !bConnected ) break; - if ( credentials.HasSessionToken && credentials.AppTicket != null ) + if ( credentials.HasSessionToken && credentials.AppTicket != null && Licenses != null ) break; if ( callback == null ) @@ -162,6 +169,21 @@ namespace DepotDownloader credentials.SessionToken = msg.SessionToken; credentials.HasSessionToken = true; } + + if ( callback.IsType() ) + { + var msg = callback as SteamApps.LicenseListCallback; + + if ( msg.Result != EResult.OK ) + { + Console.WriteLine( "Unable to get license list: {0} ", msg.Result ); + steamUser.LogOff(); + break; + } + + Console.WriteLine( "Got {0} licenses for account!", msg.LicenseList.Count ); + Licenses = msg.LicenseList; + } } credentialHandle.Set();