Patched SteamUGC

Bad DownloadAsync implementation
This commit is contained in:
SeaFood6913 2024-02-27 15:26:27 +01:00
parent 5028bcb2be
commit 3c705d6315
2 changed files with 45 additions and 44 deletions

View File

@ -29,7 +29,7 @@ internal override bool InitializeInterface( bool server )
internal static void InstallEvents( bool server ) internal static void InstallEvents( bool server )
{ {
Dispatch.Install<DownloadItemResult_t>( x => OnDownloadItemResult?.Invoke( x.Result ), server ); Dispatch.Install<DownloadItemResult_t>( x => OnDownloadItemResult?.Invoke( x.AppID.Value, x.PublishedFileId, x.Result ), server );
Dispatch.Install<RemoteStoragePublishedFileSubscribed_t>( x => OnItemSubscribed?.Invoke( x.AppID.Value, x.PublishedFileId ), server ); Dispatch.Install<RemoteStoragePublishedFileSubscribed_t>( x => OnItemSubscribed?.Invoke( x.AppID.Value, x.PublishedFileId ), server );
Dispatch.Install<RemoteStoragePublishedFileUnsubscribed_t>( x => OnItemUnsubscribed?.Invoke( x.AppID.Value, x.PublishedFileId ), server ); Dispatch.Install<RemoteStoragePublishedFileUnsubscribed_t>( x => OnItemUnsubscribed?.Invoke( x.AppID.Value, x.PublishedFileId ), server );
Dispatch.Install<ItemInstalled_t>( x => OnItemInstalled?.Invoke( x.AppID.Value, x.PublishedFileId ), server ); Dispatch.Install<ItemInstalled_t>( x => OnItemInstalled?.Invoke( x.AppID.Value, x.PublishedFileId ), server );
@ -38,7 +38,7 @@ internal static void InstallEvents( bool server )
/// <summary> /// <summary>
/// Invoked after an item is downloaded. /// Invoked after an item is downloaded.
/// </summary> /// </summary>
public static event Action<Result> OnDownloadItemResult; public static event Action<AppId, PublishedFileId, Result> OnDownloadItemResult;
/// <summary> /// <summary>
/// Invoked when a new item is subscribed. /// Invoked when a new item is subscribed.
@ -67,74 +67,63 @@ public static bool Download( PublishedFileId fileId, bool highPriority = false )
/// <summary> /// <summary>
/// Will attempt to download this item asyncronously - allowing you to instantly react to its installation. /// Will attempt to download this item asyncronously - allowing you to instantly react to its installation.
/// </summary> /// </summary>
/// <param name="appId"></param>
/// <param name="fileId">The ID of the file you download.</param> /// <param name="fileId">The ID of the file you download.</param>
/// <param name="progress">An optional callback</param> /// <param name="progress">An optional callback</param>
/// <param name="ct">Allows to send a message to cancel the download anywhere during the process.</param> /// <param name="ct">Allows to send a message to cancel the download anywhere during the process.</param>
/// <param name="milisecondsUpdateDelay">How often to call the progress function.</param> /// <param name="milisecondsUpdateDelay">How often to call the progress function.</param>
/// <returns><see langword="true"/> if downloaded and installed properly.</returns> /// <returns><see langword="true"/> if downloaded and installed properly.</returns>
public static async Task<bool> DownloadAsync( PublishedFileId fileId, Action<float> progress = null, int milisecondsUpdateDelay = 60, CancellationToken ct = default ) public static async Task<bool> DownloadAsync( AppId appId, PublishedFileId fileId, Action<float> progress = null, int milisecondsUpdateDelay = 60, CancellationToken ct = default )
{ {
var item = new Steamworks.Ugc.Item( fileId ); var item = new Steamworks.Ugc.Item( fileId );
if ( ct == default )
ct = new CancellationTokenSource( TimeSpan.FromSeconds( 60 ) ).Token;
progress?.Invoke( 0.0f ); progress?.Invoke( 0.0f );
if ( Download( fileId, true ) == false ) Result result = Result.None;
return item.IsInstalled;
// Steam docs about Download: Action<AppId, PublishedFileId, Result> onDownloadStarted = ( appIdCallback, fileIdInCallback, resultInCallback ) =>
// If the return value is true then register and wait
// for the Callback DownloadItemResult_t before calling
// GetItemInstallInfo or accessing the workshop item on disk.
// Wait for DownloadItemResult_t
{ {
Action<Result> onDownloadStarted = null; if ( appIdCallback == appId && fileIdInCallback == fileId )
result = resultInCallback;
};
try SteamUGC.OnDownloadItemResult += onDownloadStarted;
{ if ( SteamUGC.Download( fileId, true ) == false )
var downloadStarted = false; {
SteamUGC.OnDownloadItemResult -= onDownloadStarted;
onDownloadStarted = r => downloadStarted = true; return item.IsInstalled;
OnDownloadItemResult += onDownloadStarted;
while ( downloadStarted == false )
{
if ( ct.IsCancellationRequested )
break;
await Task.Delay( milisecondsUpdateDelay );
}
}
finally
{
OnDownloadItemResult -= onDownloadStarted;
}
} }
progress?.Invoke( 0.2f ); try
await Task.Delay( milisecondsUpdateDelay );
//Wait for downloading completion
{ {
while ( true ) while ( true )
{ {
if ( ct.IsCancellationRequested ) if ( ct != default && ct.IsCancellationRequested )
break; break;
progress?.Invoke( 0.2f + item.DownloadAmount * 0.8f ); if ( !item.IsDownloading )
progress?.Invoke( 0.1f );
else
progress?.Invoke( 0.1f + item.DownloadAmount * 0.85f );
if ( !item.IsDownloading && item.IsInstalled ) if ( !item.IsDownloading && item.IsInstalled && result != Result.None )
break; break;
await Task.Delay( milisecondsUpdateDelay ); await Task.Delay( milisecondsUpdateDelay );
} }
if ( result != Result.OK && result != Result.None )
return false;
if ( ct.IsCancellationRequested )
return false;
}
finally
{
SteamUGC.OnDownloadItemResult -= onDownloadStarted;
} }
progress?.Invoke( 1.0f ); progress?.Invoke( 1.0f );
return item.IsInstalled; return item.IsInstalled;
} }
@ -176,6 +165,18 @@ public static async Task<bool> StopPlaytimeTrackingForAllItems()
return result.Value.Result == Result.OK; return result.Value.Result == Result.OK;
} }
public static uint GetSubscribedItems(List<PublishedFileId> subscribedItems)
{
if (subscribedItems == null) return 0;
uint numItems = Internal.GetNumSubscribedItems();
PublishedFileId[] items = new PublishedFileId[numItems];
numItems = Internal.GetSubscribedItems( items, numItems );
for ( int i = 0; i < numItems; i++ )
subscribedItems.Add( items[i] );
return numItems;
}
/// <summary> /// <summary>
/// Suspends all workshop downloads. /// Suspends all workshop downloads.
/// Downloads will be suspended until you resume them by calling <see cref="ResumeDownloads"/> or when the game ends. /// Downloads will be suspended until you resume them by calling <see cref="ResumeDownloads"/> or when the game ends.

View File

@ -283,9 +283,9 @@ public async Task<bool> Subscribe ()
/// If CancellationToken is default then there is 60 seconds timeout /// If CancellationToken is default then there is 60 seconds timeout
/// Progress will be set to 0-1 /// Progress will be set to 0-1
/// </summary> /// </summary>
public async Task<bool> DownloadAsync( Action<float> progress = null, int milisecondsUpdateDelay = 60, CancellationToken ct = default ) public async Task<bool> DownloadAsync( AppId appId, Action<float> progress = null, int milisecondsUpdateDelay = 60, CancellationToken ct = default )
{ {
return await SteamUGC.DownloadAsync( Id, progress, milisecondsUpdateDelay, ct ); return await SteamUGC.DownloadAsync( appId, Id, progress, milisecondsUpdateDelay, ct );
} }
/// <summary> /// <summary>