diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index 967cc499..a59a69fb 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -4,6 +4,7 @@ using System; using System.Buffers; using System.Collections.Concurrent; +using System.Collections.Frozen; using System.Collections.Generic; using System.IO; using System.Linq; @@ -35,6 +36,16 @@ namespace DepotDownloader private const string CONFIG_DIR = ".DepotDownloader"; private static readonly string STAGING_DIR = Path.Combine(CONFIG_DIR, "staging"); + private static readonly FrozenSet SupportedWorkshopFileTypes = FrozenSet.ToFrozenSet(new[] + { + EWorkshopFileType.Community, + EWorkshopFileType.Art, + EWorkshopFileType.Screenshot, + EWorkshopFileType.Merch, + EWorkshopFileType.IntegratedGuide, + EWorkshopFileType.ControllerBinding, + }); + private sealed class DepotDownloadInfo( uint depotid, uint appId, ulong manifestId, string branch, string installDir, byte[] depotKey) @@ -334,22 +345,55 @@ namespace DepotDownloader steam3.Disconnect(); } - - public static async Task DownloadPubfileAsync(uint appId, ulong publishedFileId) + private static async Task ProcessPublishedFileAsync(uint appId, ulong publishedFileId, List> fileUrls, List contentFileIds) { var details = await steam3.GetPublishedFileDetails(appId, publishedFileId); + var fileType = (EWorkshopFileType)details.file_type; - if (!string.IsNullOrEmpty(details?.file_url)) + if (fileType == EWorkshopFileType.Collection) { - await DownloadWebFile(appId, details.filename, details.file_url); + foreach (var child in details.children) + { + await ProcessPublishedFileAsync(appId, child.publishedfileid, fileUrls, contentFileIds); + } } - else if (details?.hcontent_file > 0) + else if (SupportedWorkshopFileTypes.Contains(fileType)) { - await DownloadAppAsync(appId, new List<(uint, ulong)> { (appId, details.hcontent_file) }, DEFAULT_BRANCH, null, null, null, false, true); + if (!string.IsNullOrEmpty(details?.file_url)) + { + fileUrls.Add((details.filename, details.file_url)); + } + else if (details?.hcontent_file > 0) + { + contentFileIds.Add(details.hcontent_file); + } + else + { + Console.WriteLine("Unable to locate manifest ID for published file {0}", publishedFileId); + } } else { - Console.WriteLine("Unable to locate manifest ID for published file {0}", publishedFileId); + Console.WriteLine("Published file {0} has unsupported file type {1}. Skipping file", publishedFileId, fileType); + } + } + + public static async Task DownloadPubfileAsync(uint appId, ulong publishedFileId) + { + List> fileUrls = new(); + List contentFileIds = new(); + + await ProcessPublishedFileAsync(appId, publishedFileId, fileUrls, contentFileIds); + + foreach (var item in fileUrls) + { + await DownloadWebFile(appId, item.Item1, item.Item2); + } + + if (contentFileIds.Count > 0) + { + var depotManifestIds = contentFileIds.Select(id => (appId, id)).ToList(); + await DownloadAppAsync(appId, depotManifestIds, DEFAULT_BRANCH, null, null, null, false, true); } } diff --git a/DepotDownloader/Steam3Session.cs b/DepotDownloader/Steam3Session.cs index 0b9f8555..bff4f3ca 100644 --- a/DepotDownloader/Steam3Session.cs +++ b/DepotDownloader/Steam3Session.cs @@ -333,7 +333,11 @@ namespace DepotDownloader public async Task GetPublishedFileDetails(uint appId, PublishedFileID pubFile) { - var pubFileRequest = new CPublishedFile_GetDetails_Request { appid = appId }; + var pubFileRequest = new CPublishedFile_GetDetails_Request + { + appid = appId, + includechildren = true, + }; pubFileRequest.publishedfileids.Add(pubFile); var details = await steamPublishedFile.GetDetails(pubFileRequest);