Add roslyn-like .editorconfig (#236)

pull/232/head
js6pak 4 years ago committed by GitHub
parent 33483e594b
commit afab5e44b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,7 +1,230 @@
; EditorConfig: http://EditorConfig.org # top-most EditorConfig file
root = true root = true
[*] [*]
indent_style = space indent_style = space
charset = utf-8
end_of_line = lf
insert_final_newline = true
# Code files
[*.{cs, csx, vb, vbx}]
indent_size = 4 indent_size = 4
# XML project files
[*.{csproj, vbproj, vcxproj, vcxproj.filters, proj, projitems, shproj}]
indent_size = 2
# XML config files
[*.{props, targets, ruleset, config, nuspec, resx, vsixmanifest, vsct}]
indent_size = 2
# Dotnet code style settings:
[*.{cs, vb}]
# IDE0055: Fix formatting
dotnet_diagnostic.IDE0055.severity = warning
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:refactoring
dotnet_style_qualification_for_property = false:refactoring
dotnet_style_qualification_for_method = false:refactoring
dotnet_style_qualification_for_event = false:refactoring
# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Suggest more modern language features when available
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
# Non-private static fields are PascalCase
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
# Non-private readonly fields are PascalCase
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style
dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
# Constants are PascalCase
dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.constant_style.capitalization = pascal_case
# Static readonly fields are PascalCase
dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static, readonly
dotnet_naming_style.static_field_style.capitalization = pascal_case
# Instance fields are camelCase and start with _
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
dotnet_naming_symbols.instance_fields.applicable_kinds = field
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _
# Locals and parameters are camelCase
dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
dotnet_naming_style.camel_case_style.capitalization = camel_case
# Local functions are PascalCase
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_style.local_function_style.capitalization = pascal_case
# By default, name items with PascalCase
dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.all_members.applicable_kinds = *
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Async methods should have "Async" suffix
dotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods
dotnet_naming_rule.async_methods_end_in_async.style = end_in_async
dotnet_naming_rule.async_methods_end_in_async.severity = warning
dotnet_naming_symbols.any_async_methods.applicable_kinds = method
dotnet_naming_symbols.any_async_methods.applicable_accessibilities = *
dotnet_naming_symbols.any_async_methods.required_modifiers = async
dotnet_naming_style.end_in_async.required_prefix =
dotnet_naming_style.end_in_async.required_suffix = Async
dotnet_naming_style.end_in_async.capitalization = pascal_case
dotnet_naming_style.end_in_async.word_separator =
# error RS2008: Enable analyzer release tracking for the analyzer project containing rule '{0}'
dotnet_diagnostic.RS2008.severity = none
# IDE0005: Remove unnecessary import
dotnet_diagnostic.IDE0005.severity = warning
# IDE0007: Use `var` instead of explicit type
dotnet_diagnostic.IDE0007.severity = warning
# IDE0035: Remove unreachable code
dotnet_diagnostic.IDE0035.severity = warning
# IDE0036: Order modifiers
dotnet_diagnostic.IDE0036.severity = warning
# IDE0043: Format string contains invalid placeholder
dotnet_diagnostic.IDE0043.severity = warning
# IDE0044: Make field readonly
dotnet_diagnostic.IDE0044.severity = warning
# CSharp code style settings:
[*.cs]
# Newline settings
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
# csharp_new_line_before_members_in_object_initializers = true TODO seems like Rider/ReSharper has the value inverted, uncomment when its fixed
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = false
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Prefer "var" everywhere
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
# Prefer method-like constructs to have a block body
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Suggest more modern language features when available
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = do_not_ignore
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Blocks are allowed
csharp_prefer_braces = true:silent
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true

@ -1,12 +1,10 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using ProtoBuf;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.IO.IsolatedStorage; using System.IO.IsolatedStorage;
using System.Linq; using ProtoBuf;
using SteamKit2;
using SteamKit2.Discovery;
namespace DepotDownloader namespace DepotDownloader
{ {
@ -17,17 +15,17 @@ namespace DepotDownloader
public Dictionary<string, byte[]> SentryData { get; private set; } public Dictionary<string, byte[]> SentryData { get; private set; }
[ProtoMember(2, IsRequired = false)] [ProtoMember(2, IsRequired = false)]
public System.Collections.Concurrent.ConcurrentDictionary<string, int> ContentServerPenalty { get; private set; } public ConcurrentDictionary<string, int> ContentServerPenalty { get; private set; }
[ProtoMember(3, IsRequired = false)] [ProtoMember(3, IsRequired = false)]
public Dictionary<string, string> LoginKeys { get; private set; } public Dictionary<string, string> LoginKeys { get; private set; }
string FileName = null; string FileName;
AccountSettingsStore() AccountSettingsStore()
{ {
SentryData = new Dictionary<string, byte[]>(); SentryData = new Dictionary<string, byte[]>();
ContentServerPenalty = new System.Collections.Concurrent.ConcurrentDictionary<string, int>(); ContentServerPenalty = new ConcurrentDictionary<string, int>();
LoginKeys = new Dictionary<string, string>(); LoginKeys = new Dictionary<string, string>();
} }
@ -36,7 +34,7 @@ namespace DepotDownloader
get { return Instance != null; } get { return Instance != null; }
} }
public static AccountSettingsStore Instance = null; public static AccountSettingsStore Instance;
static readonly IsolatedStorageFile IsolatedStorage = IsolatedStorageFile.GetUserStoreForAssembly(); static readonly IsolatedStorageFile IsolatedStorage = IsolatedStorageFile.GetUserStoreForAssembly();
public static void LoadFromFile(string filename) public static void LoadFromFile(string filename)
@ -49,9 +47,9 @@ namespace DepotDownloader
try try
{ {
using (var fs = IsolatedStorage.OpenFile(filename, FileMode.Open, FileAccess.Read)) using (var fs = IsolatedStorage.OpenFile(filename, FileMode.Open, FileAccess.Read))
using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Decompress)) using (var ds = new DeflateStream(fs, CompressionMode.Decompress))
{ {
Instance = ProtoBuf.Serializer.Deserialize<AccountSettingsStore>(ds); Instance = Serializer.Deserialize<AccountSettingsStore>(ds);
} }
} }
catch (IOException ex) catch (IOException ex)
@ -76,9 +74,9 @@ namespace DepotDownloader
try try
{ {
using (var fs = IsolatedStorage.OpenFile(Instance.FileName, FileMode.Create, FileAccess.Write)) using (var fs = IsolatedStorage.OpenFile(Instance.FileName, FileMode.Create, FileAccess.Write))
using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Compress)) using (var ds = new DeflateStream(fs, CompressionMode.Compress))
{ {
ProtoBuf.Serializer.Serialize<AccountSettingsStore>(ds, Instance); Serializer.Serialize(ds, Instance);
} }
} }
catch (IOException ex) catch (IOException ex)

@ -1,11 +1,11 @@
using SteamKit2; using System;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SteamKit2;
namespace DepotDownloader namespace DepotDownloader
{ {
@ -82,7 +82,7 @@ namespace DepotDownloader
private async Task ConnectionPoolMonitorAsync() private async Task ConnectionPoolMonitorAsync()
{ {
bool didPopulate = false; var didPopulate = false;
while (!shutdownToken.IsCancellationRequested) while (!shutdownToken.IsCancellationRequested)
{ {
@ -165,11 +165,9 @@ namespace DepotDownloader
var result = await authTokenCallbackPromise.Task; var result = await authTokenCallbackPromise.Task;
return result.Token; return result.Token;
} }
else
{
throw new Exception($"Failed to retrieve CDN token for server {server.Host} depot {depotId}"); throw new Exception($"Failed to retrieve CDN token for server {server.Host} depot {depotId}");
} }
}
public void ReturnConnection(CDNClient.Server server) public void ReturnConnection(CDNClient.Server server)
{ {

@ -1,19 +1,16 @@
using SteamKit2; using System;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SteamKit2;
namespace DepotDownloader namespace DepotDownloader
{ {
public class ContentDownloaderException : System.Exception public class ContentDownloaderException : Exception
{ {
public ContentDownloaderException(String value) : base(value) { } public ContentDownloaderException(String value) : base(value) { }
} }
@ -58,11 +55,11 @@ namespace DepotDownloader
installDir = null; installDir = null;
try try
{ {
if ( string.IsNullOrWhiteSpace( ContentDownloader.Config.InstallDirectory ) ) if (string.IsNullOrWhiteSpace(Config.InstallDirectory))
{ {
Directory.CreateDirectory(DEFAULT_DOWNLOAD_DIR); Directory.CreateDirectory(DEFAULT_DOWNLOAD_DIR);
string depotPath = Path.Combine( DEFAULT_DOWNLOAD_DIR, depotId.ToString() ); var depotPath = Path.Combine(DEFAULT_DOWNLOAD_DIR, depotId.ToString());
Directory.CreateDirectory(depotPath); Directory.CreateDirectory(depotPath);
installDir = Path.Combine(depotPath, depotVersion.ToString()); installDir = Path.Combine(depotPath, depotVersion.ToString());
@ -73,9 +70,9 @@ namespace DepotDownloader
} }
else else
{ {
Directory.CreateDirectory( ContentDownloader.Config.InstallDirectory ); Directory.CreateDirectory(Config.InstallDirectory);
installDir = ContentDownloader.Config.InstallDirectory; installDir = Config.InstallDirectory;
Directory.CreateDirectory(Path.Combine(installDir, CONFIG_DIR)); Directory.CreateDirectory(Path.Combine(installDir, CONFIG_DIR));
Directory.CreateDirectory(Path.Combine(installDir, STAGING_DIR)); Directory.CreateDirectory(Path.Combine(installDir, STAGING_DIR));
@ -101,9 +98,9 @@ namespace DepotDownloader
return true; return true;
} }
foreach ( Regex rgx in Config.FilesToDownloadRegex ) foreach (var rgx in Config.FilesToDownloadRegex)
{ {
Match m = rgx.Match( filename ); var m = rgx.Match(filename);
if (m.Success) if (m.Success)
return true; return true;
@ -120,7 +117,7 @@ namespace DepotDownloader
IEnumerable<uint> licenseQuery; IEnumerable<uint> licenseQuery;
if (steam3.steamUser.SteamID.AccountType == EAccountType.AnonUser) if (steam3.steamUser.SteamID.AccountType == EAccountType.AnonUser)
{ {
licenseQuery = new List<uint>() { 17906 }; licenseQuery = new List<uint> { 17906 };
} }
else else
{ {
@ -158,7 +155,7 @@ namespace DepotDownloader
return null; return null;
} }
KeyValue appinfo = app.KeyValues; var appinfo = app.KeyValues;
string section_key; string section_key;
switch (section) switch (section)
@ -179,7 +176,7 @@ namespace DepotDownloader
throw new NotImplementedException(); throw new NotImplementedException();
} }
KeyValue section_kv = appinfo.Children.Where( c => c.Name == section_key ).FirstOrDefault(); var section_kv = appinfo.Children.Where(c => c.Name == section_key).FirstOrDefault();
return section_kv; return section_kv;
} }
@ -189,14 +186,14 @@ namespace DepotDownloader
return 0; return 0;
KeyValue depots = ContentDownloader.GetSteam3AppSection( appId, EAppInfoSection.Depots ); var depots = GetSteam3AppSection(appId, EAppInfoSection.Depots);
KeyValue branches = depots[ "branches" ]; var branches = depots["branches"];
KeyValue node = branches[ branch ]; var node = branches[branch];
if (node == KeyValue.Invalid) if (node == KeyValue.Invalid)
return 0; return 0;
KeyValue buildid = node[ "buildid" ]; var buildid = node["buildid"];
if (buildid == KeyValue.Invalid) if (buildid == KeyValue.Invalid)
return 0; return 0;
@ -206,8 +203,8 @@ namespace DepotDownloader
static ulong GetSteam3DepotManifest(uint depotId, uint appId, string branch) static ulong GetSteam3DepotManifest(uint depotId, uint appId, string branch)
{ {
KeyValue depots = GetSteam3AppSection( appId, EAppInfoSection.Depots ); var depots = GetSteam3AppSection(appId, EAppInfoSection.Depots);
KeyValue depotChild = depots[ depotId.ToString() ]; var depotChild = depots[depotId.ToString()];
if (depotChild == KeyValue.Invalid) if (depotChild == KeyValue.Invalid)
return INVALID_MANIFEST_ID; return INVALID_MANIFEST_ID;
@ -217,7 +214,7 @@ namespace DepotDownloader
// Rather than relay on the unknown sharedinstall key, just look for manifests. Test cases: 111710, 346680. // Rather than relay on the unknown sharedinstall key, just look for manifests. Test cases: 111710, 346680.
if (depotChild["manifests"] == KeyValue.Invalid && depotChild["depotfromapp"] != KeyValue.Invalid) if (depotChild["manifests"] == KeyValue.Invalid && depotChild["depotfromapp"] != KeyValue.Invalid)
{ {
uint otherAppId = depotChild["depotfromapp"].AsUnsignedInteger(); var otherAppId = depotChild["depotfromapp"].AsUnsignedInteger();
if (otherAppId == appId) if (otherAppId == appId)
{ {
// This shouldn't ever happen, but ya never know with Valve. Don't infinite loop. // This shouldn't ever happen, but ya never know with Valve. Don't infinite loop.
@ -244,7 +241,7 @@ namespace DepotDownloader
var node_encrypted = manifests_encrypted[branch]; var node_encrypted = manifests_encrypted[branch];
if (node_encrypted != KeyValue.Invalid) if (node_encrypted != KeyValue.Invalid)
{ {
string password = Config.BetaPassword; var password = Config.BetaPassword;
if (password == null) if (password == null)
{ {
Console.Write("Please enter the password for branch {0}: ", branch); Console.Write("Please enter the password for branch {0}: ", branch);
@ -256,8 +253,8 @@ namespace DepotDownloader
if (encrypted_v1 != KeyValue.Invalid) if (encrypted_v1 != KeyValue.Invalid)
{ {
byte[] input = Util.DecodeHexString( encrypted_v1.Value ); var input = Util.DecodeHexString(encrypted_v1.Value);
byte[] manifest_bytes = CryptoHelper.VerifyAndDecryptPassword( input, password ); var manifest_bytes = CryptoHelper.VerifyAndDecryptPassword(input, password);
if (manifest_bytes == null) if (manifest_bytes == null)
{ {
@ -267,7 +264,8 @@ namespace DepotDownloader
return BitConverter.ToUInt64(manifest_bytes, 0); return BitConverter.ToUInt64(manifest_bytes, 0);
} }
else if ( encrypted_v2 != KeyValue.Invalid )
if (encrypted_v2 != KeyValue.Invalid)
{ {
// Submit the password to Steam now to get encryption keys // Submit the password to Steam now to get encryption keys
steam3.CheckAppBetaPassword(appId, Config.BetaPassword); steam3.CheckAppBetaPassword(appId, Config.BetaPassword);
@ -278,7 +276,7 @@ namespace DepotDownloader
return INVALID_MANIFEST_ID; return INVALID_MANIFEST_ID;
} }
byte[] input = Util.DecodeHexString( encrypted_v2.Value ); var input = Util.DecodeHexString(encrypted_v2.Value);
byte[] manifest_bytes; byte[] manifest_bytes;
try try
{ {
@ -292,14 +290,11 @@ namespace DepotDownloader
return BitConverter.ToUInt64(manifest_bytes, 0); return BitConverter.ToUInt64(manifest_bytes, 0);
} }
else
{
Console.WriteLine("Unhandled depot encryption for depotId {0}", depotId); Console.WriteLine("Unhandled depot encryption for depotId {0}", depotId);
return INVALID_MANIFEST_ID; return INVALID_MANIFEST_ID;
} }
}
return INVALID_MANIFEST_ID; return INVALID_MANIFEST_ID;
} }
@ -313,28 +308,26 @@ namespace DepotDownloader
{ {
if (depotId == INVALID_DEPOT_ID) if (depotId == INVALID_DEPOT_ID)
{ {
KeyValue info = GetSteam3AppSection( appId, EAppInfoSection.Common ); var info = GetSteam3AppSection(appId, EAppInfoSection.Common);
if (info == null) if (info == null)
return String.Empty; return String.Empty;
return info["name"].AsString(); return info["name"].AsString();
} }
else
{ var depots = GetSteam3AppSection(appId, EAppInfoSection.Depots);
KeyValue depots = GetSteam3AppSection( appId, EAppInfoSection.Depots );
if (depots == null) if (depots == null)
return String.Empty; return String.Empty;
KeyValue depotChild = depots[ depotId.ToString() ]; var depotChild = depots[depotId.ToString()];
if (depotChild == null) if (depotChild == null)
return String.Empty; return String.Empty;
return depotChild["name"].AsString(); return depotChild["name"].AsString();
} }
}
public static bool InitializeSteam3(string username, string password) public static bool InitializeSteam3(string username, string password)
{ {
@ -346,7 +339,7 @@ namespace DepotDownloader
} }
steam3 = new Steam3Session( steam3 = new Steam3Session(
new SteamUser.LogOnDetails() new SteamUser.LogOnDetails
{ {
Username = username, Username = username,
Password = loginKey == null ? password : null, Password = loginKey == null ? password : null,
@ -392,7 +385,7 @@ namespace DepotDownloader
} }
else if (details?.hcontent_file > 0) else if (details?.hcontent_file > 0)
{ {
await DownloadAppAsync( appId, new List<(uint, ulong)>() { ( appId, details.hcontent_file ) }, DEFAULT_BRANCH, null, null, null, false, true ); await DownloadAppAsync(appId, new List<(uint, ulong)> { (appId, details.hcontent_file) }, DEFAULT_BRANCH, null, null, null, false, true);
} }
else else
{ {
@ -419,7 +412,7 @@ namespace DepotDownloader
} }
else else
{ {
await DownloadAppAsync( appId, new List<(uint, ulong)>() { ( appId, ugcId ) }, DEFAULT_BRANCH, null, null, null, false, true ); await DownloadAppAsync(appId, new List<(uint, ulong)> { (appId, ugcId) }, DEFAULT_BRANCH, null, null, null, false, true);
} }
} }
@ -460,7 +453,7 @@ namespace DepotDownloader
cdnPool = new CDNClientPool(steam3, appId); cdnPool = new CDNClientPool(steam3, appId);
// Load our configuration data containing the depots currently installed // Load our configuration data containing the depots currently installed
string configPath = ContentDownloader.Config.InstallDirectory; var configPath = Config.InstallDirectory;
if (string.IsNullOrWhiteSpace(configPath)) if (string.IsNullOrWhiteSpace(configPath))
{ {
configPath = DEFAULT_DOWNLOAD_DIR; configPath = DEFAULT_DOWNLOAD_DIR;
@ -483,7 +476,7 @@ namespace DepotDownloader
} }
else else
{ {
string contentName = GetAppOrDepotName( INVALID_DEPOT_ID, appId ); var contentName = GetAppOrDepotName(INVALID_DEPOT_ID, appId);
throw new ContentDownloaderException(String.Format("App {0} ({1}) is not available from this account.", appId, contentName)); throw new ContentDownloaderException(String.Format("App {0} ({1}) is not available from this account.", appId, contentName));
} }
} }
@ -491,7 +484,7 @@ namespace DepotDownloader
var hasSpecificDepots = depotManifestIds.Count > 0; var hasSpecificDepots = depotManifestIds.Count > 0;
var depotIdsFound = new List<uint>(); var depotIdsFound = new List<uint>();
var depotIdsExpected = depotManifestIds.Select(x => x.Item1).ToList(); var depotIdsExpected = depotManifestIds.Select(x => x.Item1).ToList();
KeyValue depots = GetSteam3AppSection( appId, EAppInfoSection.Depots ); var depots = GetSteam3AppSection(appId, EAppInfoSection.Depots);
if (isUgc) if (isUgc)
{ {
@ -512,7 +505,7 @@ namespace DepotDownloader
{ {
foreach (var depotSection in depots.Children) foreach (var depotSection in depots.Children)
{ {
uint id = INVALID_DEPOT_ID; var id = INVALID_DEPOT_ID;
if (depotSection.Children.Count == 0) if (depotSection.Children.Count == 0)
continue; continue;
@ -563,14 +556,16 @@ namespace DepotDownloader
depotIdsFound.Add(id); depotIdsFound.Add(id);
if (!hasSpecificDepots) if (!hasSpecificDepots)
depotManifestIds.Add( ( id, ContentDownloader.INVALID_MANIFEST_ID ) ); depotManifestIds.Add((id, INVALID_MANIFEST_ID));
} }
} }
if (depotManifestIds.Count == 0 && !hasSpecificDepots) if (depotManifestIds.Count == 0 && !hasSpecificDepots)
{ {
throw new ContentDownloaderException(String.Format("Couldn't find any depots to download for app {0}", appId)); throw new ContentDownloaderException(String.Format("Couldn't find any depots to download for app {0}", appId));
} }
else if ( depotIdsFound.Count < depotIdsExpected.Count )
if (depotIdsFound.Count < depotIdsExpected.Count)
{ {
var remainingDepotIds = depotIdsExpected.Except(depotIdsFound); var remainingDepotIds = depotIdsExpected.Except(depotIdsFound);
throw new ContentDownloaderException(String.Format("Depot {0} not listed for app {1}", string.Join(", ", remainingDepotIds), appId)); throw new ContentDownloaderException(String.Format("Depot {0} not listed for app {1}", string.Join(", ", remainingDepotIds), appId));
@ -602,9 +597,9 @@ namespace DepotDownloader
static DepotDownloadInfo GetDepotInfo(uint depotId, uint appId, ulong manifestId, string branch) static DepotDownloadInfo GetDepotInfo(uint depotId, uint appId, ulong manifestId, string branch)
{ {
if (steam3 != null && appId != INVALID_APP_ID) if (steam3 != null && appId != INVALID_APP_ID)
steam3.RequestAppInfo( ( uint )appId ); steam3.RequestAppInfo(appId);
string contentName = GetAppOrDepotName( depotId, appId ); var contentName = GetAppOrDepotName(depotId, appId);
if (!AccountHasAccess(depotId)) if (!AccountHasAccess(depotId))
{ {
@ -630,7 +625,7 @@ namespace DepotDownloader
} }
} }
uint uVersion = GetSteam3AppBuildNumber( appId, branch ); var uVersion = GetSteam3AppBuildNumber(appId, branch);
string installDir; string installDir;
if (!CreateDirectories(depotId, uVersion, out installDir)) if (!CreateDirectories(depotId, uVersion, out installDir))
@ -646,7 +641,7 @@ namespace DepotDownloader
return null; return null;
} }
byte[] depotKey = steam3.DepotKeys[ depotId ]; var depotKey = steam3.DepotKeys[depotId];
var info = new DepotDownloadInfo(depotId, manifestId, installDir, contentName); var info = new DepotDownloadInfo(depotId, manifestId, installDir, contentName);
info.depotKey = depotKey; info.depotKey = depotKey;
@ -660,6 +655,7 @@ namespace DepotDownloader
OldChunk = oldChunk; OldChunk = oldChunk;
NewChunk = newChunk; NewChunk = newChunk;
} }
public ProtoManifest.ChunkData OldChunk { get; private set; } public ProtoManifest.ChunkData OldChunk { get; private set; }
public ProtoManifest.ChunkData NewChunk { get; private set; } public ProtoManifest.ChunkData NewChunk { get; private set; }
} }
@ -694,15 +690,14 @@ namespace DepotDownloader
public ulong SizeDownloaded; public ulong SizeDownloaded;
public ulong DepotBytesCompressed; public ulong DepotBytesCompressed;
public ulong DepotBytesUncompressed; public ulong DepotBytesUncompressed;
} }
private static async Task DownloadSteam3Async(uint appId, List<DepotDownloadInfo> depots) private static async Task DownloadSteam3Async(uint appId, List<DepotDownloadInfo> depots)
{ {
CancellationTokenSource cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cdnPool.ExhaustedToken = cts; cdnPool.ExhaustedToken = cts;
GlobalDownloadCounter downloadCounter = new GlobalDownloadCounter(); var downloadCounter = new GlobalDownloadCounter();
var depotsToDownload = new List<DepotFilesData>(depots.Count); var depotsToDownload = new List<DepotFilesData>(depots.Count);
var allFileNamesAllDepots = new HashSet<String>(); var allFileNamesAllDepots = new HashSet<String>();
@ -722,7 +717,7 @@ namespace DepotDownloader
// If we're about to write all the files to the same directory, we will need to first de-duplicate any files by path // If we're about to write all the files to the same directory, we will need to first de-duplicate any files by path
// This is in last-depot-wins order, from Steam or the list of depots supplied by the user // This is in last-depot-wins order, from Steam or the list of depots supplied by the user
if (!string.IsNullOrWhiteSpace(ContentDownloader.Config.InstallDirectory) && depotsToDownload.Count > 0) if (!string.IsNullOrWhiteSpace(Config.InstallDirectory) && depotsToDownload.Count > 0)
{ {
var claimedFileNames = new HashSet<String>(); var claimedFileNames = new HashSet<String>();
@ -747,15 +742,15 @@ namespace DepotDownloader
private static async Task<DepotFilesData> ProcessDepotManifestAndFiles(CancellationTokenSource cts, private static async Task<DepotFilesData> ProcessDepotManifestAndFiles(CancellationTokenSource cts,
uint appId, DepotDownloadInfo depot) uint appId, DepotDownloadInfo depot)
{ {
DepotDownloadCounter depotCounter = new DepotDownloadCounter(); var depotCounter = new DepotDownloadCounter();
Console.WriteLine("Processing depot {0} - {1}", depot.id, depot.contentName); Console.WriteLine("Processing depot {0} - {1}", depot.id, depot.contentName);
ProtoManifest oldProtoManifest = null; ProtoManifest oldProtoManifest = null;
ProtoManifest newProtoManifest = null; ProtoManifest newProtoManifest = null;
string configDir = Path.Combine(depot.installDir, CONFIG_DIR); var configDir = Path.Combine(depot.installDir, CONFIG_DIR);
ulong lastManifestId = INVALID_MANIFEST_ID; var lastManifestId = INVALID_MANIFEST_ID;
DepotConfigStore.Instance.InstalledManifestIDs.TryGetValue(depot.id, out lastManifestId); DepotConfigStore.Instance.InstalledManifestIDs.TryGetValue(depot.id, out lastManifestId);
// In case we have an early exit, this will force equiv of verifyall next run. // In case we have an early exit, this will force equiv of verifyall next run.
@ -863,16 +858,15 @@ namespace DepotDownloader
Console.WriteLine("Encountered 401 for depot manifest {0} {1}. Aborting.", depot.id, depot.manifestId); Console.WriteLine("Encountered 401 for depot manifest {0} {1}. Aborting.", depot.id, depot.manifestId);
break; break;
} }
else if (e.StatusCode == HttpStatusCode.NotFound)
if (e.StatusCode == HttpStatusCode.NotFound)
{ {
Console.WriteLine("Encountered 404 for depot manifest {0} {1}. Aborting.", depot.id, depot.manifestId); Console.WriteLine("Encountered 404 for depot manifest {0} {1}. Aborting.", depot.id, depot.manifestId);
break; break;
} }
else
{
Console.WriteLine("Encountered error downloading depot manifest {0} {1}: {2}", depot.id, depot.manifestId, e.StatusCode); Console.WriteLine("Encountered error downloading depot manifest {0} {1}: {2}", depot.id, depot.manifestId, e.StatusCode);
} }
}
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
break; break;
@ -882,8 +876,7 @@ namespace DepotDownloader
cdnPool.ReturnBrokenConnection(connection); cdnPool.ReturnBrokenConnection(connection);
Console.WriteLine("Encountered error downloading manifest for depot {0} {1}: {2}", depot.id, depot.manifestId, e.Message); Console.WriteLine("Encountered error downloading manifest for depot {0} {1}: {2}", depot.id, depot.manifestId, e.Message);
} }
} } while (depotManifest == null);
while (depotManifest == null);
if (depotManifest == null) if (depotManifest == null)
{ {
@ -914,7 +907,7 @@ namespace DepotDownloader
return null; return null;
} }
string stagingDir = Path.Combine(depot.installDir, STAGING_DIR); var stagingDir = Path.Combine(depot.installDir, STAGING_DIR);
var filesAfterExclusions = newProtoManifest.Files.AsParallel().Where(f => TestIsFileIncluded(f.FileName)).ToList(); var filesAfterExclusions = newProtoManifest.Files.AsParallel().Where(f => TestIsFileIncluded(f.FileName)).ToList();
var allFileNames = new HashSet<string>(filesAfterExclusions.Count); var allFileNames = new HashSet<string>(filesAfterExclusions.Count);
@ -984,7 +977,7 @@ namespace DepotDownloader
var previousFilteredFiles = depotFilesData.previousManifest.Files.AsParallel().Where(f => TestIsFileIncluded(f.FileName)).Select(f => f.FileName).ToHashSet(); var previousFilteredFiles = depotFilesData.previousManifest.Files.AsParallel().Where(f => TestIsFileIncluded(f.FileName)).Select(f => f.FileName).ToHashSet();
// Check if we are writing to a single output directory. If not, each depot folder is managed independently // Check if we are writing to a single output directory. If not, each depot folder is managed independently
if (string.IsNullOrWhiteSpace(ContentDownloader.Config.InstallDirectory)) if (string.IsNullOrWhiteSpace(Config.InstallDirectory))
{ {
// Of the list of files in the previous manifest, remove any file names that exist in the current set of all file names // Of the list of files in the previous manifest, remove any file names that exist in the current set of all file names
previousFilteredFiles.ExceptWith(depotFilesData.allFileNames); previousFilteredFiles.ExceptWith(depotFilesData.allFileNames);
@ -997,7 +990,7 @@ namespace DepotDownloader
foreach (var existingFileName in previousFilteredFiles) foreach (var existingFileName in previousFilteredFiles)
{ {
string fileFinalPath = Path.Combine(depot.installDir, existingFileName); var fileFinalPath = Path.Combine(depot.installDir, existingFileName);
if (!File.Exists(fileFinalPath)) if (!File.Exists(fileFinalPath))
continue; continue;
@ -1026,8 +1019,8 @@ namespace DepotDownloader
var depotDownloadCounter = depotFilesData.depotCounter; var depotDownloadCounter = depotFilesData.depotCounter;
var oldProtoManifest = depotFilesData.previousManifest; var oldProtoManifest = depotFilesData.previousManifest;
string fileFinalPath = Path.Combine(depot.installDir, file.FileName); var fileFinalPath = Path.Combine(depot.installDir, file.FileName);
string fileStagingPath = Path.Combine(stagingDir, file.FileName); var fileStagingPath = Path.Combine(stagingDir, file.FileName);
// This may still exist if the previous run exited before cleanup // This may still exist if the previous run exited before cleanup
if (File.Exists(fileStagingPath)) if (File.Exists(fileStagingPath))
@ -1037,7 +1030,7 @@ namespace DepotDownloader
FileStream fs = null; FileStream fs = null;
List<ProtoManifest.ChunkData> neededChunks; List<ProtoManifest.ChunkData> neededChunks;
FileInfo fi = new FileInfo(fileFinalPath); var fi = new FileInfo(fileFinalPath);
if (!fi.Exists) if (!fi.Exists)
{ {
Console.WriteLine("Pre-allocating {0}", fileFinalPath); Console.WriteLine("Pre-allocating {0}", fileFinalPath);
@ -1052,6 +1045,7 @@ namespace DepotDownloader
{ {
throw new ContentDownloaderException(String.Format("Failed to allocate file {0}: {1}", fileFinalPath, ex.Message)); throw new ContentDownloaderException(String.Format("Failed to allocate file {0}: {1}", fileFinalPath, ex.Message));
} }
neededChunks = new List<ProtoManifest.ChunkData>(file.Chunks); neededChunks = new List<ProtoManifest.ChunkData>(file.Chunks);
} }
else else
@ -1101,10 +1095,10 @@ namespace DepotDownloader
{ {
fsOld.Seek((long)match.OldChunk.Offset, SeekOrigin.Begin); fsOld.Seek((long)match.OldChunk.Offset, SeekOrigin.Begin);
byte[] tmp = new byte[match.OldChunk.UncompressedLength]; var tmp = new byte[match.OldChunk.UncompressedLength];
fsOld.Read(tmp, 0, tmp.Length); fsOld.Read(tmp, 0, tmp.Length);
byte[] adler = Util.AdlerHash(tmp); var adler = Util.AdlerHash(tmp);
if (!adler.SequenceEqual(match.OldChunk.Checksum)) if (!adler.SequenceEqual(match.OldChunk.Checksum))
{ {
neededChunks.Add(match.NewChunk); neededChunks.Add(match.NewChunk);
@ -1136,7 +1130,7 @@ namespace DepotDownloader
{ {
fsOld.Seek((long)match.OldChunk.Offset, SeekOrigin.Begin); fsOld.Seek((long)match.OldChunk.Offset, SeekOrigin.Begin);
byte[] tmp = new byte[match.OldChunk.UncompressedLength]; var tmp = new byte[match.OldChunk.UncompressedLength];
fsOld.Read(tmp, 0, tmp.Length); fsOld.Read(tmp, 0, tmp.Length);
fs.Seek((long)match.NewChunk.Offset, SeekOrigin.Begin); fs.Seek((long)match.NewChunk.Offset, SeekOrigin.Begin);
@ -1173,25 +1167,23 @@ namespace DepotDownloader
{ {
lock (depotDownloadCounter) lock (depotDownloadCounter)
{ {
depotDownloadCounter.SizeDownloaded += (ulong)file.TotalSize; depotDownloadCounter.SizeDownloaded += file.TotalSize;
Console.WriteLine("{0,6:#00.00}% {1}", ((float)depotDownloadCounter.SizeDownloaded / (float)depotDownloadCounter.CompleteDownloadSize) * 100.0f, fileFinalPath); Console.WriteLine("{0,6:#00.00}% {1}", (depotDownloadCounter.SizeDownloaded / (float)depotDownloadCounter.CompleteDownloadSize) * 100.0f, fileFinalPath);
} }
if (fs != null) if (fs != null)
fs.Dispose(); fs.Dispose();
return; return;
} }
else
{
var sizeOnDisk = (file.TotalSize - (ulong)neededChunks.Select(x => (long)x.UncompressedLength).Sum()); var sizeOnDisk = (file.TotalSize - (ulong)neededChunks.Select(x => (long)x.UncompressedLength).Sum());
lock (depotDownloadCounter) lock (depotDownloadCounter)
{ {
depotDownloadCounter.SizeDownloaded += sizeOnDisk; depotDownloadCounter.SizeDownloaded += sizeOnDisk;
} }
} }
}
FileStreamData fileStreamData = new FileStreamData var fileStreamData = new FileStreamData
{ {
fileStream = fs, fileStream = fs,
fileLock = new SemaphoreSlim(1), fileLock = new SemaphoreSlim(1),
@ -1217,9 +1209,9 @@ namespace DepotDownloader
var depot = depotFilesData.depotDownloadInfo; var depot = depotFilesData.depotDownloadInfo;
var depotDownloadCounter = depotFilesData.depotCounter; var depotDownloadCounter = depotFilesData.depotCounter;
string chunkID = Util.EncodeHexString(chunk.ChunkID); var chunkID = Util.EncodeHexString(chunk.ChunkID);
DepotManifest.ChunkData data = new DepotManifest.ChunkData(); var data = new DepotManifest.ChunkData();
data.ChunkID = chunk.ChunkID; data.ChunkID = chunk.ChunkID;
data.Checksum = chunk.Checksum; data.Checksum = chunk.Checksum;
data.Offset = chunk.Offset; data.Offset = chunk.Offset;
@ -1260,11 +1252,9 @@ namespace DepotDownloader
Console.WriteLine("Encountered 401 for chunk {0}. Aborting.", chunkID); Console.WriteLine("Encountered 401 for chunk {0}. Aborting.", chunkID);
break; break;
} }
else
{
Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, e.StatusCode); Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, e.StatusCode);
} }
}
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
break; break;
@ -1274,8 +1264,7 @@ namespace DepotDownloader
cdnPool.ReturnBrokenConnection(connection); cdnPool.ReturnBrokenConnection(connection);
Console.WriteLine("Encountered unexpected error downloading chunk {0}: {1}", chunkID, e.Message); Console.WriteLine("Encountered unexpected error downloading chunk {0}: {1}", chunkID, e.Message);
} }
} } while (chunkData == null);
while (chunkData == null);
if (chunkData == null) if (chunkData == null)
{ {
@ -1298,7 +1287,7 @@ namespace DepotDownloader
fileStreamData.fileLock.Release(); fileStreamData.fileLock.Release();
} }
int remainingChunks = Interlocked.Decrement(ref fileStreamData.chunksToDownload); var remainingChunks = Interlocked.Decrement(ref fileStreamData.chunksToDownload);
if (remainingChunks == 0) if (remainingChunks == 0)
{ {
fileStreamData.fileStream.Dispose(); fileStreamData.fileStream.Dispose();
@ -1323,9 +1312,8 @@ namespace DepotDownloader
if (remainingChunks == 0) if (remainingChunks == 0)
{ {
var fileFinalPath = Path.Combine(depot.installDir, file.FileName); var fileFinalPath = Path.Combine(depot.installDir, file.FileName);
Console.WriteLine("{0,6:#00.00}% {1}", ((float)sizeDownloaded / (float)depotDownloadCounter.CompleteDownloadSize) * 100.0f, fileFinalPath); Console.WriteLine("{0,6:#00.00}% {1}", (sizeDownloaded / (float)depotDownloadCounter.CompleteDownloadSize) * 100.0f, fileFinalPath);
} }
} }
static void DumpManifestToTextFile(DepotDownloadInfo depot, ProtoManifest manifest) static void DumpManifestToTextFile(DepotDownloadInfo depot, ProtoManifest manifest)

@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ProtoBuf;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using ProtoBuf;
namespace DepotDownloader namespace DepotDownloader
{ {
@ -12,7 +12,7 @@ namespace DepotDownloader
[ProtoMember(1)] [ProtoMember(1)]
public Dictionary<uint, ulong> InstalledManifestIDs { get; private set; } public Dictionary<uint, ulong> InstalledManifestIDs { get; private set; }
string FileName = null; string FileName;
DepotConfigStore() DepotConfigStore()
{ {
@ -24,7 +24,7 @@ namespace DepotDownloader
get { return Instance != null; } get { return Instance != null; }
} }
public static DepotConfigStore Instance = null; public static DepotConfigStore Instance;
public static void LoadFromFile(string filename) public static void LoadFromFile(string filename)
{ {
@ -33,9 +33,9 @@ namespace DepotDownloader
if (File.Exists(filename)) if (File.Exists(filename))
{ {
using (FileStream fs = File.Open(filename, FileMode.Open)) using (var fs = File.Open(filename, FileMode.Open))
using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Decompress)) using (var ds = new DeflateStream(fs, CompressionMode.Decompress))
Instance = ProtoBuf.Serializer.Deserialize<DepotConfigStore>(ds); Instance = Serializer.Deserialize<DepotConfigStore>(ds);
} }
else else
{ {
@ -50,9 +50,9 @@ namespace DepotDownloader
if (!Loaded) if (!Loaded)
throw new Exception("Saved config before loading"); throw new Exception("Saved config before loading");
using (FileStream fs = File.Open(Instance.FileName, FileMode.Create)) using (var fs = File.Open(Instance.FileName, FileMode.Create))
using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Compress)) using (var ds = new DeflateStream(fs, CompressionMode.Compress))
ProtoBuf.Serializer.Serialize<DepotConfigStore>(ds, Instance); Serializer.Serialize(ds, Instance);
} }
} }
} }

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<Version>2.4.3</Version> <Version>2.4.3</Version>
<Description>Steam Downloading Utility</Description> <Description>Steam Downloading Utility</Description>

@ -1,11 +1,7 @@
using System; using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -33,7 +29,7 @@ namespace DepotDownloader
// By default, we create dual-mode sockets: // By default, we create dual-mode sockets:
// Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp); // Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.NoDelay = true; socket.NoDelay = true;
try try

@ -26,7 +26,7 @@ namespace DepotDownloader
protected override void OnEventWritten(EventWrittenEventArgs eventData) protected override void OnEventWritten(EventWrittenEventArgs eventData)
{ {
var sb = new StringBuilder().Append($"{eventData.TimeStamp:HH:mm:ss.fffffff} {eventData.EventSource.Name}.{eventData.EventName}("); var sb = new StringBuilder().Append($"{eventData.TimeStamp:HH:mm:ss.fffffff} {eventData.EventSource.Name}.{eventData.EventName}(");
for (int i = 0; i < eventData.Payload?.Count; i++) for (var i = 0; i < eventData.Payload?.Count; i++)
{ {
sb.Append(eventData.PayloadNames?[i]).Append(": ").Append(eventData.Payload[i]); sb.Append(eventData.PayloadNames?[i]).Append(": ").Append(eventData.Payload[i]);
if (i < eventData.Payload?.Count - 1) if (i < eventData.Payload?.Count - 1)

@ -1,11 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using SteamKit2;
using System.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using SteamKit2;
namespace DepotDownloader namespace DepotDownloader
{ {
@ -39,13 +39,13 @@ namespace DepotDownloader
var httpEventListener = new HttpDiagnosticEventListener(); var httpEventListener = new HttpDiagnosticEventListener();
} }
string username = GetParameter<string>( args, "-username" ) ?? GetParameter<string>( args, "-user" ); var username = GetParameter<string>(args, "-username") ?? GetParameter<string>(args, "-user");
string password = GetParameter<string>( args, "-password" ) ?? GetParameter<string>( args, "-pass" ); var password = GetParameter<string>(args, "-password") ?? GetParameter<string>(args, "-pass");
ContentDownloader.Config.RememberPassword = HasParameter(args, "-remember-password"); ContentDownloader.Config.RememberPassword = HasParameter(args, "-remember-password");
ContentDownloader.Config.DownloadManifestOnly = HasParameter(args, "-manifest-only"); ContentDownloader.Config.DownloadManifestOnly = HasParameter(args, "-manifest-only");
int cellId = GetParameter<int>( args, "-cellid", -1 ); var cellId = GetParameter(args, "-cellid", -1);
if (cellId == -1) if (cellId == -1)
{ {
cellId = 0; cellId = 0;
@ -53,14 +53,14 @@ namespace DepotDownloader
ContentDownloader.Config.CellID = cellId; ContentDownloader.Config.CellID = cellId;
string fileList = GetParameter<string>( args, "-filelist" ); var fileList = GetParameter<string>(args, "-filelist");
if (fileList != null) if (fileList != null)
{ {
try try
{ {
string fileListData = await File.ReadAllTextAsync( fileList ); var fileListData = await File.ReadAllTextAsync(fileList);
var files = fileListData.Split( new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries ); var files = fileListData.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
ContentDownloader.Config.UsingFileList = true; ContentDownloader.Config.UsingFileList = true;
ContentDownloader.Config.FilesToDownload = new HashSet<string>(StringComparer.OrdinalIgnoreCase); ContentDownloader.Config.FilesToDownload = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
@ -70,7 +70,7 @@ namespace DepotDownloader
{ {
if (fileEntry.StartsWith("regex:")) if (fileEntry.StartsWith("regex:"))
{ {
Regex rgx = new Regex( fileEntry.Substring( 6 ), RegexOptions.Compiled | RegexOptions.IgnoreCase ); var rgx = new Regex(fileEntry.Substring(6), RegexOptions.Compiled | RegexOptions.IgnoreCase);
ContentDownloader.Config.FilesToDownloadRegex.Add(rgx); ContentDownloader.Config.FilesToDownloadRegex.Add(rgx);
} }
else else
@ -83,29 +83,29 @@ namespace DepotDownloader
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine( "Warning: Unable to load filelist: {0}", ex.ToString() ); Console.WriteLine("Warning: Unable to load filelist: {0}", ex);
} }
} }
ContentDownloader.Config.InstallDirectory = GetParameter<string>(args, "-dir"); ContentDownloader.Config.InstallDirectory = GetParameter<string>(args, "-dir");
ContentDownloader.Config.VerifyAll = HasParameter(args, "-verify-all") || HasParameter(args, "-verify_all") || HasParameter(args, "-validate"); ContentDownloader.Config.VerifyAll = HasParameter(args, "-verify-all") || HasParameter(args, "-verify_all") || HasParameter(args, "-validate");
ContentDownloader.Config.MaxServers = GetParameter<int>( args, "-max-servers", 20 ); ContentDownloader.Config.MaxServers = GetParameter(args, "-max-servers", 20);
ContentDownloader.Config.MaxDownloads = GetParameter<int>( args, "-max-downloads", 8 ); ContentDownloader.Config.MaxDownloads = GetParameter(args, "-max-downloads", 8);
ContentDownloader.Config.MaxServers = Math.Max(ContentDownloader.Config.MaxServers, ContentDownloader.Config.MaxDownloads); ContentDownloader.Config.MaxServers = Math.Max(ContentDownloader.Config.MaxServers, ContentDownloader.Config.MaxDownloads);
ContentDownloader.Config.LoginID = HasParameter( args, "-loginid" ) ? (uint?)GetParameter<uint>( args, "-loginid" ) : null; ContentDownloader.Config.LoginID = HasParameter(args, "-loginid") ? GetParameter<uint>(args, "-loginid") : null;
#endregion #endregion
uint appId = GetParameter<uint>( args, "-app", ContentDownloader.INVALID_APP_ID ); var appId = GetParameter(args, "-app", ContentDownloader.INVALID_APP_ID);
if (appId == ContentDownloader.INVALID_APP_ID) if (appId == ContentDownloader.INVALID_APP_ID)
{ {
Console.WriteLine("Error: -app not specified!"); Console.WriteLine("Error: -app not specified!");
return 1; return 1;
} }
ulong pubFile = GetParameter<ulong>( args, "-pubfile", ContentDownloader.INVALID_MANIFEST_ID ); var pubFile = GetParameter(args, "-pubfile", ContentDownloader.INVALID_MANIFEST_ID);
ulong ugcId = GetParameter<ulong>( args, "-ugc", ContentDownloader.INVALID_MANIFEST_ID ); var ugcId = GetParameter(args, "-ugc", ContentDownloader.INVALID_MANIFEST_ID);
if (pubFile != ContentDownloader.INVALID_MANIFEST_ID) if (pubFile != ContentDownloader.INVALID_MANIFEST_ID)
{ {
#region Pubfile Downloading #region Pubfile Downloading
@ -180,11 +180,11 @@ namespace DepotDownloader
{ {
#region App downloading #region App downloading
string branch = GetParameter<string>( args, "-branch" ) ?? GetParameter<string>( args, "-beta" ) ?? ContentDownloader.DEFAULT_BRANCH; var branch = GetParameter<string>(args, "-branch") ?? GetParameter<string>(args, "-beta") ?? ContentDownloader.DEFAULT_BRANCH;
ContentDownloader.Config.BetaPassword = GetParameter<string>(args, "-betapassword"); ContentDownloader.Config.BetaPassword = GetParameter<string>(args, "-betapassword");
ContentDownloader.Config.DownloadAllPlatforms = HasParameter(args, "-all-platforms"); ContentDownloader.Config.DownloadAllPlatforms = HasParameter(args, "-all-platforms");
string os = GetParameter<string>( args, "-os", null ); var os = GetParameter<string>(args, "-os");
if (ContentDownloader.Config.DownloadAllPlatforms && !String.IsNullOrEmpty(os)) if (ContentDownloader.Config.DownloadAllPlatforms && !String.IsNullOrEmpty(os))
{ {
@ -192,10 +192,10 @@ namespace DepotDownloader
return 1; return 1;
} }
string arch = GetParameter<string>( args, "-osarch", null ); var arch = GetParameter<string>(args, "-osarch");
ContentDownloader.Config.DownloadAllLanguages = HasParameter(args, "-all-languages"); ContentDownloader.Config.DownloadAllLanguages = HasParameter(args, "-all-languages");
string language = GetParameter<string>( args, "-language", null ); var language = GetParameter<string>(args, "-language");
if (ContentDownloader.Config.DownloadAllLanguages && !String.IsNullOrEmpty(language)) if (ContentDownloader.Config.DownloadAllLanguages && !String.IsNullOrEmpty(language))
{ {
@ -203,13 +203,13 @@ namespace DepotDownloader
return 1; return 1;
} }
bool lv = HasParameter( args, "-lowviolence" ); var lv = HasParameter(args, "-lowviolence");
List<(uint, ulong)> depotManifestIds = new List<(uint, ulong)>(); var depotManifestIds = new List<(uint, ulong)>();
bool isUGC = false; var isUGC = false;
List<uint> depotIdList = GetParameterList<uint>( args, "-depot" ); var depotIdList = GetParameterList<uint>(args, "-depot");
List<ulong> manifestIdList = GetParameterList<ulong>( args, "-manifest" ); var manifestIdList = GetParameterList<ulong>(args, "-manifest");
if (manifestIdList.Count > 0) if (manifestIdList.Count > 0)
{ {
if (depotIdList.Count != manifestIdList.Count) if (depotIdList.Count != manifestIdList.Count)
@ -277,6 +277,7 @@ namespace DepotDownloader
// Avoid console echoing of password // Avoid console echoing of password
password = Util.ReadPassword(); password = Util.ReadPassword();
} }
Console.WriteLine(); Console.WriteLine();
} while (String.Empty == password); } while (String.Empty == password);
} }
@ -293,13 +294,15 @@ namespace DepotDownloader
static int IndexOfParam(string[] args, string param) static int IndexOfParam(string[] args, string param)
{ {
for ( int x = 0; x < args.Length; ++x ) for (var x = 0; x < args.Length; ++x)
{ {
if (args[x].Equals(param, StringComparison.OrdinalIgnoreCase)) if (args[x].Equals(param, StringComparison.OrdinalIgnoreCase))
return x; return x;
} }
return -1; return -1;
} }
static bool HasParameter(string[] args, string param) static bool HasParameter(string[] args, string param)
{ {
return IndexOfParam(args, param) > -1; return IndexOfParam(args, param) > -1;
@ -307,12 +310,12 @@ namespace DepotDownloader
static T GetParameter<T>(string[] args, string param, T defaultValue = default(T)) static T GetParameter<T>(string[] args, string param, T defaultValue = default(T))
{ {
int index = IndexOfParam( args, param ); var index = IndexOfParam(args, param);
if (index == -1 || index == (args.Length - 1)) if (index == -1 || index == (args.Length - 1))
return defaultValue; return defaultValue;
string strParam = args[ index + 1 ]; var strParam = args[index + 1];
var converter = TypeDescriptor.GetConverter(typeof(T)); var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null) if (converter != null)
@ -325,8 +328,8 @@ namespace DepotDownloader
static List<T> GetParameterList<T>(string[] args, string param) static List<T> GetParameterList<T>(string[] args, string param)
{ {
List<T> list = new List<T>(); var list = new List<T>();
int index = IndexOfParam(args, param); var index = IndexOfParam(args, param);
if (index == -1 || index == (args.Length - 1)) if (index == -1 || index == (args.Length - 1))
return list; return list;
@ -335,7 +338,7 @@ namespace DepotDownloader
while (index < args.Length) while (index < args.Length)
{ {
string strParam = args[index]; var strParam = args[index];
if (strParam[0] == '-') break; if (strParam[0] == '-') break;

@ -2,13 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using ProtoBuf; using ProtoBuf;
using SteamKit2; using SteamKit2;
namespace DepotDownloader namespace DepotDownloader
{ {
[ProtoContract()] [ProtoContract]
class ProtoManifest class ProtoManifest
{ {
// Proto ctor // Proto ctor
@ -24,7 +23,7 @@ namespace DepotDownloader
CreationTime = sourceManifest.CreationTime; CreationTime = sourceManifest.CreationTime;
} }
[ProtoContract()] [ProtoContract]
public class FileData public class FileData
{ {
// Proto ctor // Proto ctor
@ -130,32 +129,31 @@ namespace DepotDownloader
return null; return null;
} }
using (MemoryStream ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
using (FileStream fs = File.Open(filename, FileMode.Open)) using (var fs = File.Open(filename, FileMode.Open))
using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Decompress)) using (var ds = new DeflateStream(fs, CompressionMode.Decompress))
ds.CopyTo(ms); ds.CopyTo(ms);
checksum = Util.SHAHash(ms.ToArray()); checksum = Util.SHAHash(ms.ToArray());
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
return ProtoBuf.Serializer.Deserialize<ProtoManifest>(ms); return Serializer.Deserialize<ProtoManifest>(ms);
} }
} }
public void SaveToFile(string filename, out byte[] checksum) public void SaveToFile(string filename, out byte[] checksum)
{ {
using (var ms = new MemoryStream())
using (MemoryStream ms = new MemoryStream())
{ {
ProtoBuf.Serializer.Serialize<ProtoManifest>(ms, this); Serializer.Serialize(ms, this);
checksum = Util.SHAHash(ms.ToArray()); checksum = Util.SHAHash(ms.ToArray());
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
using (FileStream fs = File.Open(filename, FileMode.Create)) using (var fs = File.Open(filename, FileMode.Create))
using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Compress)) using (var ds = new DeflateStream(fs, CompressionMode.Compress))
ms.CopyTo(ds); ms.CopyTo(ds);
} }
} }

@ -1,6 +1,4 @@
using SteamKit2; using System;
using SteamKit2.Internal;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -8,10 +6,11 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SteamKit2;
using SteamKit2.Internal;
namespace DepotDownloader namespace DepotDownloader
{ {
class Steam3Session class Steam3Session
{ {
public class Credentials public class Credentials
@ -41,13 +40,13 @@ namespace DepotDownloader
public SteamClient steamClient; public SteamClient steamClient;
public SteamUser steamUser; public SteamUser steamUser;
SteamApps steamApps; readonly SteamApps steamApps;
SteamCloud steamCloud; readonly SteamCloud steamCloud;
SteamUnifiedMessages.UnifiedService<IPublishedFile> steamPublishedFile; readonly SteamUnifiedMessages.UnifiedService<IPublishedFile> steamPublishedFile;
CallbackManager callbacks; readonly CallbackManager callbacks;
bool authenticatedUser; readonly bool authenticatedUser;
bool bConnected; bool bConnected;
bool bConnecting; bool bConnecting;
bool bAborted; bool bAborted;
@ -60,10 +59,10 @@ namespace DepotDownloader
DateTime connectTime; DateTime connectTime;
// input // input
SteamUser.LogOnDetails logonDetails; readonly SteamUser.LogOnDetails logonDetails;
// output // output
Credentials credentials; readonly Credentials credentials;
static readonly TimeSpan STEAM3_TIMEOUT = TimeSpan.FromSeconds(30); static readonly TimeSpan STEAM3_TIMEOUT = TimeSpan.FromSeconds(30);
@ -117,7 +116,7 @@ namespace DepotDownloader
if (authenticatedUser) if (authenticatedUser)
{ {
FileInfo fi = new FileInfo( String.Format( "{0}.sentryFile", logonDetails.Username ) ); var fi = new FileInfo(String.Format("{0}.sentryFile", logonDetails.Username));
if (AccountSettingsStore.Instance.SentryData != null && AccountSettingsStore.Instance.SentryData.ContainsKey(logonDetails.Username)) if (AccountSettingsStore.Instance.SentryData != null && AccountSettingsStore.Instance.SentryData.ContainsKey(logonDetails.Username))
{ {
logonDetails.SentryFileHash = Util.SHAHash(AccountSettingsStore.Instance.SentryData[logonDetails.Username]); logonDetails.SentryFileHash = Util.SHAHash(AccountSettingsStore.Instance.SentryData[logonDetails.Username]);
@ -135,7 +134,8 @@ namespace DepotDownloader
} }
public delegate bool WaitCondition(); public delegate bool WaitCondition();
private object steamLock = new object();
private readonly object steamLock = new object();
public bool WaitUntilCallback(Action submitter, WaitCondition waiter) public bool WaitUntilCallback(Action submitter, WaitCondition waiter)
{ {
@ -146,15 +146,14 @@ namespace DepotDownloader
submitter(); submitter();
} }
int seq = this.seq; var seq = this.seq;
do do
{ {
lock (steamLock) lock (steamLock)
{ {
WaitForCallbacks(); WaitForCallbacks();
} }
} } while (!bAborted && this.seq == seq && !waiter());
while ( !bAborted && this.seq == seq && !waiter() );
} }
return bAborted; return bAborted;
@ -175,8 +174,8 @@ namespace DepotDownloader
if ((AppInfo.ContainsKey(appId) && !bForce) || bAborted) if ((AppInfo.ContainsKey(appId) && !bForce) || bAborted)
return; return;
bool completed = false; var completed = false;
Action<SteamApps.PICSTokensCallback> cbMethodTokens = ( appTokens ) => Action<SteamApps.PICSTokensCallback> cbMethodTokens = appTokens =>
{ {
completed = true; completed = true;
if (appTokens.AppTokensDenied.Contains(appId)) if (appTokens.AppTokensDenied.Contains(appId))
@ -192,11 +191,11 @@ namespace DepotDownloader
WaitUntilCallback(() => WaitUntilCallback(() =>
{ {
callbacks.Subscribe( steamApps.PICSGetAccessTokens( new List<uint>() { appId }, new List<uint>() { } ), cbMethodTokens ); callbacks.Subscribe(steamApps.PICSGetAccessTokens(new List<uint> { appId }, new List<uint>()), cbMethodTokens);
}, () => { return completed; }); }, () => { return completed; });
completed = false; completed = false;
Action<SteamApps.PICSProductInfoCallback> cbMethod = ( appInfo ) => Action<SteamApps.PICSProductInfoCallback> cbMethod = appInfo =>
{ {
completed = !appInfo.ResponsePending; completed = !appInfo.ResponsePending;
@ -214,7 +213,7 @@ namespace DepotDownloader
} }
}; };
SteamApps.PICSRequest request = new SteamApps.PICSRequest( appId ); var request = new SteamApps.PICSRequest(appId);
if (AppTokens.ContainsKey(appId)) if (AppTokens.ContainsKey(appId))
{ {
request.AccessToken = AppTokens[appId]; request.AccessToken = AppTokens[appId];
@ -223,20 +222,20 @@ namespace DepotDownloader
WaitUntilCallback(() => WaitUntilCallback(() =>
{ {
callbacks.Subscribe( steamApps.PICSGetProductInfo( new List<SteamApps.PICSRequest>() { request }, new List<SteamApps.PICSRequest>() { } ), cbMethod ); callbacks.Subscribe(steamApps.PICSGetProductInfo(new List<SteamApps.PICSRequest> { request }, new List<SteamApps.PICSRequest>()), cbMethod);
}, () => { return completed; }); }, () => { return completed; });
} }
public void RequestPackageInfo(IEnumerable<uint> packageIds) public void RequestPackageInfo(IEnumerable<uint> packageIds)
{ {
List<uint> packages = packageIds.ToList(); var packages = packageIds.ToList();
packages.RemoveAll(pid => PackageInfo.ContainsKey(pid)); packages.RemoveAll(pid => PackageInfo.ContainsKey(pid));
if (packages.Count == 0 || bAborted) if (packages.Count == 0 || bAborted)
return; return;
bool completed = false; var completed = false;
Action<SteamApps.PICSProductInfoCallback> cbMethod = ( packageInfo ) => Action<SteamApps.PICSProductInfoCallback> cbMethod = packageInfo =>
{ {
completed = !packageInfo.ResponsePending; completed = !packageInfo.ResponsePending;
@ -275,9 +274,9 @@ namespace DepotDownloader
public bool RequestFreeAppLicense(uint appId) public bool RequestFreeAppLicense(uint appId)
{ {
bool success = false; var success = false;
bool completed = false; var completed = false;
Action<SteamApps.FreeLicenseCallback> cbMethod = ( resultInfo ) => Action<SteamApps.FreeLicenseCallback> cbMethod = resultInfo =>
{ {
completed = true; completed = true;
success = resultInfo.GrantedApps.Contains(appId); success = resultInfo.GrantedApps.Contains(appId);
@ -296,9 +295,9 @@ namespace DepotDownloader
if (DepotKeys.ContainsKey(depotId) || bAborted) if (DepotKeys.ContainsKey(depotId) || bAborted)
return; return;
bool completed = false; var completed = false;
Action<SteamApps.DepotKeyCallback> cbMethod = ( depotKey ) => Action<SteamApps.DepotKeyCallback> cbMethod = depotKey =>
{ {
completed = true; completed = true;
Console.WriteLine("Got depot key for {0} result: {1}", depotKey.DepotID, depotKey.Result); Console.WriteLine("Got depot key for {0} result: {1}", depotKey.DepotID, depotKey.Result);
@ -325,7 +324,8 @@ namespace DepotDownloader
{ {
return "steampipe.steamcontent.com"; return "steampipe.steamcontent.com";
} }
else if (host.EndsWith(".steamcontent.com"))
if (host.EndsWith(".steamcontent.com"))
{ {
return "steamcontent.com"; return "steamcontent.com";
} }
@ -341,9 +341,9 @@ namespace DepotDownloader
if (!CDNAuthTokens.TryAdd(cdnKey, new TaskCompletionSource<SteamApps.CDNAuthTokenCallback>())) if (!CDNAuthTokens.TryAdd(cdnKey, new TaskCompletionSource<SteamApps.CDNAuthTokenCallback>()))
return; return;
bool completed = false; var completed = false;
var timeoutDate = DateTime.Now.AddSeconds(10); var timeoutDate = DateTime.Now.AddSeconds(10);
Action<SteamApps.CDNAuthTokenCallback> cbMethod = ( cdnAuth ) => Action<SteamApps.CDNAuthTokenCallback> cbMethod = cdnAuth =>
{ {
completed = true; completed = true;
Console.WriteLine("Got CDN auth token for {0} result: {1} (expires {2})", host, cdnAuth.Result, cdnAuth.Expiration); Console.WriteLine("Got CDN auth token for {0} result: {1} (expires {2})", host, cdnAuth.Result, cdnAuth.Expiration);
@ -365,8 +365,8 @@ namespace DepotDownloader
public void CheckAppBetaPassword(uint appid, string password) public void CheckAppBetaPassword(uint appid, string password)
{ {
bool completed = false; var completed = false;
Action<SteamApps.CheckAppBetaPasswordCallback> cbMethod = ( appPassword ) => Action<SteamApps.CheckAppBetaPasswordCallback> cbMethod = appPassword =>
{ {
completed = true; completed = true;
@ -386,10 +386,10 @@ namespace DepotDownloader
public PublishedFileDetails GetPublishedFileDetails(uint appId, PublishedFileID pubFile) public PublishedFileDetails GetPublishedFileDetails(uint appId, PublishedFileID pubFile)
{ {
var pubFileRequest = new CPublishedFile_GetDetails_Request() { appid = appId }; var pubFileRequest = new CPublishedFile_GetDetails_Request { appid = appId };
pubFileRequest.publishedfileids.Add(pubFile); pubFileRequest.publishedfileids.Add(pubFile);
bool completed = false; var completed = false;
PublishedFileDetails details = null; PublishedFileDetails details = null;
Action<SteamUnifiedMessages.ServiceMethodResponse> cbMethod = callback => Action<SteamUnifiedMessages.ServiceMethodResponse> cbMethod = callback =>
@ -417,7 +417,7 @@ namespace DepotDownloader
public SteamCloud.UGCDetailsCallback GetUGCDetails(UGCHandle ugcHandle) public SteamCloud.UGCDetailsCallback GetUGCDetails(UGCHandle ugcHandle)
{ {
bool completed = false; var completed = false;
SteamCloud.UGCDetailsCallback details = null; SteamCloud.UGCDetailsCallback details = null;
Action<SteamCloud.UGCDetailsCallback> cbMethod = callback => Action<SteamCloud.UGCDetailsCallback> cbMethod = callback =>
@ -470,6 +470,7 @@ namespace DepotDownloader
{ {
Disconnect(sendLogOff); Disconnect(sendLogOff);
} }
public void Disconnect(bool sendLogOff = true) public void Disconnect(bool sendLogOff = true)
{ {
if (sendLogOff) if (sendLogOff)
@ -504,7 +505,7 @@ namespace DepotDownloader
while (true) while (true)
{ {
DateTime now = DateTime.Now; var now = DateTime.Now;
if (now >= totalWaitPeriod) break; if (now >= totalWaitPeriod) break;
if (bDidReceiveLoginKey) break; if (bDidReceiveLoginKey) break;
@ -517,14 +518,12 @@ namespace DepotDownloader
{ {
callbacks.RunWaitCallbacks(TimeSpan.FromSeconds(1)); callbacks.RunWaitCallbacks(TimeSpan.FromSeconds(1));
TimeSpan diff = DateTime.Now - connectTime; var diff = DateTime.Now - connectTime;
if (diff > STEAM3_TIMEOUT && !bConnected) if (diff > STEAM3_TIMEOUT && !bConnected)
{ {
Console.WriteLine("Timeout connecting to Steam3."); Console.WriteLine("Timeout connecting to Steam3.");
Abort(); Abort();
return;
} }
} }
@ -583,9 +582,9 @@ namespace DepotDownloader
private void LogOnCallback(SteamUser.LoggedOnCallback loggedOn) private void LogOnCallback(SteamUser.LoggedOnCallback loggedOn)
{ {
bool isSteamGuard = loggedOn.Result == EResult.AccountLogonDenied; var isSteamGuard = loggedOn.Result == EResult.AccountLogonDenied;
bool is2FA = loggedOn.Result == EResult.AccountLoginDeniedNeedTwoFactor; var is2FA = loggedOn.Result == EResult.AccountLoginDeniedNeedTwoFactor;
bool isLoginKey = ContentDownloader.Config.RememberPassword && logonDetails.LoginKey != null && loggedOn.Result == EResult.InvalidPassword; var isLoginKey = ContentDownloader.Config.RememberPassword && logonDetails.LoginKey != null && loggedOn.Result == EResult.InvalidPassword;
if (isSteamGuard || is2FA || isLoginKey) if (isSteamGuard || is2FA || isLoginKey)
{ {
@ -631,7 +630,8 @@ namespace DepotDownloader
return; return;
} }
else if ( loggedOn.Result == EResult.TryAnotherCM )
if (loggedOn.Result == EResult.TryAnotherCM)
{ {
Console.Write("Retrying Steam3 connection (TryAnotherCM)..."); Console.Write("Retrying Steam3 connection (TryAnotherCM)...");
@ -639,14 +639,16 @@ namespace DepotDownloader
return; return;
} }
else if ( loggedOn.Result == EResult.ServiceUnavailable )
if (loggedOn.Result == EResult.ServiceUnavailable)
{ {
Console.WriteLine("Unable to login to Steam3: {0}", loggedOn.Result); Console.WriteLine("Unable to login to Steam3: {0}", loggedOn.Result);
Abort(false); Abort(false);
return; return;
} }
else if ( loggedOn.Result != EResult.OK )
if (loggedOn.Result != EResult.OK)
{ {
Console.WriteLine("Unable to login to Steam3: {0}", loggedOn.Result); Console.WriteLine("Unable to login to Steam3: {0}", loggedOn.Result);
Abort(); Abort();
@ -696,7 +698,7 @@ namespace DepotDownloader
private void UpdateMachineAuthCallback(SteamUser.UpdateMachineAuthCallback machineAuth) private void UpdateMachineAuthCallback(SteamUser.UpdateMachineAuthCallback machineAuth)
{ {
byte[] hash = Util.SHAHash( machineAuth.Data ); var hash = Util.SHAHash(machineAuth.Data);
Console.WriteLine("Got Machine Auth: {0} {1} {2} {3}", machineAuth.FileName, machineAuth.Offset, machineAuth.BytesToWrite, machineAuth.Data.Length, hash); Console.WriteLine("Got Machine Auth: {0} {1} {2} {3}", machineAuth.FileName, machineAuth.Offset, machineAuth.BytesToWrite, machineAuth.Data.Length, hash);
AccountSettingsStore.Instance.SentryData[logonDetails.Username] = machineAuth.Data; AccountSettingsStore.Instance.SentryData[logonDetails.Username] = machineAuth.Data;
@ -734,7 +736,5 @@ namespace DepotDownloader
bDidReceiveLoginKey = true; bDidReceiveLoginKey = true;
} }
} }
} }

@ -17,11 +17,13 @@ namespace DepotDownloader
{ {
return "windows"; return "windows";
} }
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{ {
return "macos"; return "macos";
} }
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{ {
return "linux"; return "linux";
} }
@ -37,7 +39,7 @@ namespace DepotDownloader
public static string ReadPassword() public static string ReadPassword()
{ {
ConsoleKeyInfo keyInfo; ConsoleKeyInfo keyInfo;
StringBuilder password = new StringBuilder(); var password = new StringBuilder();
do do
{ {
@ -50,11 +52,12 @@ namespace DepotDownloader
password.Remove(password.Length - 1, 1); password.Remove(password.Length - 1, 1);
Console.Write("\x1B[1D\x1B[1P"); Console.Write("\x1B[1D\x1B[1P");
} }
continue; continue;
} }
/* Printable ASCII characters only */ /* Printable ASCII characters only */
char c = keyInfo.KeyChar; var c = keyInfo.KeyChar;
if (c >= ' ' && c <= '~') if (c >= ' ' && c <= '~')
{ {
password.Append(c); password.Append(c);
@ -73,7 +76,7 @@ namespace DepotDownloader
foreach (var data in chunkdata) foreach (var data in chunkdata)
{ {
byte[] chunk = new byte[data.UncompressedLength]; var chunk = new byte[data.UncompressedLength];
fs.Seek((long)data.Offset, SeekOrigin.Begin); fs.Seek((long)data.Offset, SeekOrigin.Begin);
read = fs.Read(chunk, 0, (int)data.UncompressedLength); read = fs.Read(chunk, 0, (int)data.UncompressedLength);
@ -88,7 +91,7 @@ namespace DepotDownloader
tempchunk = chunk; tempchunk = chunk;
} }
byte[] adler = AdlerHash(tempchunk); var adler = AdlerHash(tempchunk);
if (!adler.SequenceEqual(data.Checksum)) if (!adler.SequenceEqual(data.Checksum))
{ {
neededChunks.Add(data); neededChunks.Add(data);
@ -101,11 +104,12 @@ namespace DepotDownloader
public static byte[] AdlerHash(byte[] input) public static byte[] AdlerHash(byte[] input)
{ {
uint a = 0, b = 0; uint a = 0, b = 0;
for (int i = 0; i < input.Length; i++) for (var i = 0; i < input.Length; i++)
{ {
a = (a + input[i]) % 65521; a = (a + input[i]) % 65521;
b = (b + a) % 65521; b = (b + a) % 65521;
} }
return BitConverter.GetBytes(a | (b << 16)); return BitConverter.GetBytes(a | (b << 16));
} }
@ -124,10 +128,10 @@ namespace DepotDownloader
if (hex == null) if (hex == null)
return null; return null;
int chars = hex.Length; var chars = hex.Length;
byte[] bytes = new byte[ chars / 2 ]; var bytes = new byte[chars / 2];
for ( int i = 0 ; i < chars ; i += 2 ) for (var i = 0; i < chars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes; return bytes;
@ -145,32 +149,31 @@ namespace DepotDownloader
if (taskFactories == null) throw new ArgumentNullException(nameof(taskFactories)); if (taskFactories == null) throw new ArgumentNullException(nameof(taskFactories));
if (maxDegreeOfParallelism <= 0) throw new ArgumentException(nameof(maxDegreeOfParallelism)); if (maxDegreeOfParallelism <= 0) throw new ArgumentException(nameof(maxDegreeOfParallelism));
Func<Task>[] queue = taskFactories.ToArray(); var queue = taskFactories.ToArray();
if (queue.Length == 0) if (queue.Length == 0)
{ {
return; return;
} }
List<Task> tasksInFlight = new List<Task>(maxDegreeOfParallelism); var tasksInFlight = new List<Task>(maxDegreeOfParallelism);
int index = 0; var index = 0;
do do
{ {
while (tasksInFlight.Count < maxDegreeOfParallelism && index < queue.Length) while (tasksInFlight.Count < maxDegreeOfParallelism && index < queue.Length)
{ {
Func<Task> taskFactory = queue[index++]; var taskFactory = queue[index++];
tasksInFlight.Add(taskFactory()); tasksInFlight.Add(taskFactory());
} }
Task completedTask = await Task.WhenAny(tasksInFlight).ConfigureAwait(false); var completedTask = await Task.WhenAny(tasksInFlight).ConfigureAwait(false);
await completedTask.ConfigureAwait(false); await completedTask.ConfigureAwait(false);
tasksInFlight.Remove(completedTask); tasksInFlight.Remove(completedTask);
} } while (index < queue.Length || tasksInFlight.Count != 0);
while (index < queue.Length || tasksInFlight.Count != 0);
} }
} }
} }

Loading…
Cancel
Save