From 455a9f895691e582e32211f275ac3a305775c417 Mon Sep 17 00:00:00 2001 From: Alex Mein Date: Wed, 16 Oct 2019 14:41:57 +0100 Subject: [PATCH 1/6] Added missing public methods for various functions in ISteamUGC. Fixed UGC Submit process reporting invalid progress value. --- Facepunch.Steamworks/Structs/UgcEditor.cs | 19 +++++++++- Facepunch.Steamworks/Structs/UgcItem.cs | 37 +++++++++++++++++--- Facepunch.Steamworks/Structs/UgcQuery.cs | 7 ++++ Facepunch.Steamworks/Structs/UserItemVote.cs | 21 +++++++++++ 4 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 Facepunch.Steamworks/Structs/UserItemVote.cs diff --git a/Facepunch.Steamworks/Structs/UgcEditor.cs b/Facepunch.Steamworks/Structs/UgcEditor.cs index a97c153..b842df8 100644 --- a/Facepunch.Steamworks/Structs/UgcEditor.cs +++ b/Facepunch.Steamworks/Structs/UgcEditor.cs @@ -69,6 +69,8 @@ namespace Steamworks.Ugc public Editor WithPrivateVisibility() { Visibility = RemoteStoragePublishedFileVisibility.Private; return this; } List Tags; + Dictionary KeyValueTags; + public Editor WithTag( string tag ) { if ( Tags == null ) Tags = new List(); @@ -78,6 +80,13 @@ namespace Steamworks.Ugc return this; } + public Editor AddKeyValueTag(string key, string value) + { + if (KeyValueTags == null) KeyValueTags = new Dictionary(); + KeyValueTags.Add(key, value); + return this; + } + public async Task SubmitAsync( IProgress progress = null ) { var result = default( PublishResult ); @@ -134,6 +143,14 @@ namespace Steamworks.Ugc } } + if (KeyValueTags != null && KeyValueTags.Count > 0) + { + foreach (var keyValueTag in KeyValueTags) + { + SteamUGC.Internal.AddItemKeyValueTag(handle, keyValueTag.Key, keyValueTag.Value); + } + } + result.Result = Steamworks.Result.Fail; if ( ChangeLog == null ) @@ -171,7 +188,7 @@ namespace Steamworks.Ugc } case ItemUpdateStatus.UploadingPreviewFile: { - progress?.Report( 8f ); + progress?.Report( 0.8f ); break; } case ItemUpdateStatus.CommittingChanges: diff --git a/Facepunch.Steamworks/Structs/UgcItem.cs b/Facepunch.Steamworks/Structs/UgcItem.cs index b661aa3..09c1a61 100644 --- a/Facepunch.Steamworks/Structs/UgcItem.cs +++ b/Facepunch.Steamworks/Structs/UgcItem.cs @@ -263,6 +263,24 @@ namespace Steamworks.Ugc return result?.Result == Result.OK; } + /// + /// Adds item to user favorite list + /// + public async Task AddFavorite() + { + var result = await SteamUGC.Internal.AddItemToFavorites(details.ConsumerAppID, _id); + return result?.Result == Result.OK; + } + + /// + /// Removes item from user favorite list + /// + public async Task RemoveFavorite() + { + var result = await SteamUGC.Internal.RemoveItemFromFavorites(details.ConsumerAppID, _id); + return result?.Result == Result.OK; + } + /// /// Allows the user to rate a workshop item up or down. /// @@ -272,10 +290,21 @@ namespace Steamworks.Ugc return r?.Result == Result.OK; } - /// - /// Return a URL to view this item online - /// - public string Url => $"http://steamcommunity.com/sharedfiles/filedetails/?source=Facepunch.Steamworks&id={Id}"; + /// + /// Gets the current users vote on the item + /// + public async Task GetUserVote() + { + var result = await SteamUGC.Internal.GetUserItemVote(_id); + if (!result.HasValue) + return null; + return UserItemVote.From(result.Value); + } + + /// + /// Return a URL to view this item online + /// + public string Url => $"http://steamcommunity.com/sharedfiles/filedetails/?source=Facepunch.Steamworks&id={Id}"; /// /// The URl to view this item's changelog diff --git a/Facepunch.Steamworks/Structs/UgcQuery.cs b/Facepunch.Steamworks/Structs/UgcQuery.cs index e69ef1c..6bfd5ce 100644 --- a/Facepunch.Steamworks/Structs/UgcQuery.cs +++ b/Facepunch.Steamworks/Structs/UgcQuery.cs @@ -194,6 +194,13 @@ namespace Steamworks.Ugc return this; } + public QueryType AddRequiredKeyValueTag(string key, string value) + { + if (requiredKv == null) requiredKv = new Dictionary(); + requiredKv.Add(key, value); + return this; + } + public QueryType WithoutTag( string tag ) { if ( excludedTags == null ) excludedTags = new List(); diff --git a/Facepunch.Steamworks/Structs/UserItemVote.cs b/Facepunch.Steamworks/Structs/UserItemVote.cs new file mode 100644 index 0000000..f757443 --- /dev/null +++ b/Facepunch.Steamworks/Structs/UserItemVote.cs @@ -0,0 +1,21 @@ +using Steamworks.Data; + +namespace Steamworks.Ugc +{ + public struct UserItemVote + { + public bool VotedUp; + public bool VotedDown; + public bool VoteSkipped; + + internal static UserItemVote? From(GetUserItemVoteResult_t result) + { + return new UserItemVote + { + VotedUp = result.VotedUp, + VotedDown = result.VotedDown, + VoteSkipped = result.VoteSkipped + }; + } + } +} \ No newline at end of file From e3ce99bc12b88886b4d122b947ae43474938caaa Mon Sep 17 00:00:00 2001 From: Alex Mein Date: Wed, 16 Oct 2019 14:47:23 +0100 Subject: [PATCH 2/6] Added missing newline --- Facepunch.Steamworks/Structs/UserItemVote.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Facepunch.Steamworks/Structs/UserItemVote.cs b/Facepunch.Steamworks/Structs/UserItemVote.cs index f757443..191faed 100644 --- a/Facepunch.Steamworks/Structs/UserItemVote.cs +++ b/Facepunch.Steamworks/Structs/UserItemVote.cs @@ -18,4 +18,4 @@ namespace Steamworks.Ugc }; } } -} \ No newline at end of file +} From 4997a74d157a090146bc21469a1c70d4de763f10 Mon Sep 17 00:00:00 2001 From: Alex Mein Date: Wed, 16 Oct 2019 16:02:01 +0100 Subject: [PATCH 3/6] Added public methods for playtime tracking --- Facepunch.Steamworks/SteamUgc.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Facepunch.Steamworks/SteamUgc.cs b/Facepunch.Steamworks/SteamUgc.cs index a2f377d..a329954 100644 --- a/Facepunch.Steamworks/SteamUgc.cs +++ b/Facepunch.Steamworks/SteamUgc.cs @@ -64,5 +64,23 @@ namespace Steamworks return item; } + + public static async Task StartPlaytimeTracking(PublishedFileId fileId) + { + var result = await Internal.StartPlaytimeTracking(new[] {fileId}, 1); + return result.Value.Result == Result.OK; + } + + public static async Task StopPlaytimeTracking(PublishedFileId fileId) + { + var result = await Internal.StopPlaytimeTracking(new[] {fileId}, 1); + return result.Value.Result == Result.OK; + } + + public static async Task StopPlaytimeTrackingForAllItems() + { + var result = await Internal.StopPlaytimeTrackingForAllItems(); + return result.Value.Result == Result.OK; + } } -} \ No newline at end of file +} From f549a69bc00509865e8aa7d4714a9a3c621db126 Mon Sep 17 00:00:00 2001 From: Alex Mein Date: Fri, 18 Oct 2019 10:07:18 +0100 Subject: [PATCH 4/6] Added proper implementation of the various 'setreturn...' methods which previously did nothing --- Facepunch.Steamworks/Structs/UgcQuery.cs | 93 +++++++++++++++++++----- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/Facepunch.Steamworks/Structs/UgcQuery.cs b/Facepunch.Steamworks/Structs/UgcQuery.cs index 6bfd5ce..986bdcd 100644 --- a/Facepunch.Steamworks/Structs/UgcQuery.cs +++ b/Facepunch.Steamworks/Structs/UgcQuery.cs @@ -127,6 +127,13 @@ namespace Steamworks.Ugc handle = SteamUGC.Internal.CreateQueryAllUGCRequest1( queryType, matchingType, creatorApp.Value, consumerApp.Value, (uint)page ); } + ApplyReturns(handle); + + if (maxCacheAge.HasValue) + { + SteamUGC.Internal.SetAllowCachedResponse(handle, (uint)maxCacheAge.Value); + } + ApplyConstraints( handle ); var result = await SteamUGC.Internal.SendQueryUGCRequest( handle ); @@ -145,25 +152,8 @@ namespace Steamworks.Ugc }; } - - #region SharedConstraints + #region SharedConstraints public QueryType WithType( UgcType type ) { matchingType = type; return this; } - bool? WantsReturnOnlyIDs; - public QueryType WithOnlyIDs( bool b ) { WantsReturnOnlyIDs = b; return this; } - bool? WantsReturnKeyValueTags; - public QueryType WithKeyValueTag( bool b ) { WantsReturnKeyValueTags = b; return this; } - bool? WantsReturnLongDescription; - public QueryType WithLongDescription( bool b ) { WantsReturnLongDescription = b; return this; } - bool? WantsReturnMetadata; - public QueryType WithMetadata( bool b ) { WantsReturnMetadata = b; return this; } - bool? WantsReturnChildren; - public QueryType WithChildren( bool b ) { WantsReturnChildren = b; return this; } - bool? WantsReturnAdditionalPreviews; - public QueryType WithAdditionalPreviews( bool b ) { WantsReturnAdditionalPreviews = b; return this; } - bool? WantsReturnTotalOnly; - public QueryType WithTotalOnly( bool b ) { WantsReturnTotalOnly = b; return this; } - bool? WantsReturnPlaytimeStats; - public QueryType WithPlaytimeStats( bool b ) { WantsReturnPlaytimeStats = b; return this; } int? maxCacheAge; public QueryType AllowCachedResponse( int maxSecondsAge ) { maxCacheAge = maxSecondsAge; return this; } string language; @@ -244,7 +234,70 @@ namespace Steamworks.Ugc } } - #endregion + #endregion - } + #region ReturnValues + + bool? WantsReturnOnlyIDs; + public QueryType WithOnlyIDs(bool b) { WantsReturnOnlyIDs = b; return this; } + bool? WantsReturnKeyValueTags; + public QueryType WithKeyValueTag(bool b) { WantsReturnKeyValueTags = b; return this; } + bool? WantsReturnLongDescription; + public QueryType WithLongDescription(bool b) { WantsReturnLongDescription = b; return this; } + bool? WantsReturnMetadata; + public QueryType WithMetadata(bool b) { WantsReturnMetadata = b; return this; } + bool? WantsReturnChildren; + public QueryType WithChildren(bool b) { WantsReturnChildren = b; return this; } + bool? WantsReturnAdditionalPreviews; + public QueryType WithAdditionalPreviews(bool b) { WantsReturnAdditionalPreviews = b; return this; } + bool? WantsReturnTotalOnly; + public QueryType WithTotalOnly(bool b) { WantsReturnTotalOnly = b; return this; } + uint? WantsReturnPlaytimeStats; + public QueryType WithPlaytimeStats(uint unDays) { WantsReturnPlaytimeStats = unDays; return this; } + + private void ApplyReturns(UGCQueryHandle_t handle) + { + if (WantsReturnOnlyIDs.HasValue) + { + SteamUGC.Internal.SetReturnOnlyIDs(handle, WantsReturnOnlyIDs.Value); + } + + if (WantsReturnKeyValueTags.HasValue) + { + SteamUGC.Internal.SetReturnKeyValueTags(handle, WantsReturnKeyValueTags.Value); + } + + if (WantsReturnLongDescription.HasValue) + { + SteamUGC.Internal.SetReturnLongDescription(handle, WantsReturnLongDescription.Value); + } + + if (WantsReturnMetadata.HasValue) + { + SteamUGC.Internal.SetReturnMetadata(handle, WantsReturnMetadata.Value); + } + + if (WantsReturnChildren.HasValue) + { + SteamUGC.Internal.SetReturnChildren(handle, WantsReturnChildren.Value); + } + + if (WantsReturnAdditionalPreviews.HasValue) + { + SteamUGC.Internal.SetReturnAdditionalPreviews(handle, WantsReturnAdditionalPreviews.Value); + } + + if (WantsReturnTotalOnly.HasValue) + { + SteamUGC.Internal.SetReturnTotalOnly(handle, WantsReturnTotalOnly.Value); + } + + if (WantsReturnPlaytimeStats.HasValue) + { + SteamUGC.Internal.SetReturnPlaytimeStats(handle, WantsReturnPlaytimeStats.Value); + } + } + + #endregion + } } \ No newline at end of file From 8b231bf4d67b66102f13d9ff02774967fac461e2 Mon Sep 17 00:00:00 2001 From: Alex Mein Date: Wed, 23 Oct 2019 11:07:56 +0100 Subject: [PATCH 5/6] Made SteamUGCDetails_t.Result available via a public method in UgcItem --- Facepunch.Steamworks/Structs/UgcItem.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Facepunch.Steamworks/Structs/UgcItem.cs b/Facepunch.Steamworks/Structs/UgcItem.cs index 09c1a61..0af8321 100644 --- a/Facepunch.Steamworks/Structs/UgcItem.cs +++ b/Facepunch.Steamworks/Structs/UgcItem.cs @@ -352,6 +352,7 @@ namespace Steamworks.Ugc { return new Ugc.Editor( Id ); } + + public Result Result => details.Result; } - -} \ No newline at end of file +} From 2f63117c328d38fbd0ae6e765fca8974d7e11e05 Mon Sep 17 00:00:00 2001 From: Alex Mein Date: Mon, 28 Oct 2019 15:40:30 +0000 Subject: [PATCH 6/6] Exposed the full result of the Vote method --- Facepunch.Steamworks/Structs/UgcItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Facepunch.Steamworks/Structs/UgcItem.cs b/Facepunch.Steamworks/Structs/UgcItem.cs index 0af8321..820a581 100644 --- a/Facepunch.Steamworks/Structs/UgcItem.cs +++ b/Facepunch.Steamworks/Structs/UgcItem.cs @@ -284,10 +284,10 @@ namespace Steamworks.Ugc /// /// Allows the user to rate a workshop item up or down. /// - public async Task Vote( bool up ) + public async Task Vote( bool up ) { var r = await SteamUGC.Internal.SetUserItemVote( Id, up ); - return r?.Result == Result.OK; + return r?.Result; } ///