diff --git a/Facepunch.Steamworks/Structs/UgcEditor.cs b/Facepunch.Steamworks/Structs/UgcEditor.cs index 21251b1..18cb244 100644 --- a/Facepunch.Steamworks/Structs/UgcEditor.cs +++ b/Facepunch.Steamworks/Structs/UgcEditor.cs @@ -69,8 +69,9 @@ namespace Steamworks.Ugc public Editor WithPrivateVisibility() { Visibility = RemoteStoragePublishedFileVisibility.Private; return this; } List Tags; - Dictionary KeyValueTags; - + Dictionary> KeyValueTags; + HashSet KeyValueTagsToRemove; + public Editor WithTag( string tag ) { if ( Tags == null ) Tags = new List(); @@ -80,10 +81,37 @@ namespace Steamworks.Ugc return this; } + /// + /// Adds a key-value tag pair to an item. + /// Keys can map to multiple different values (1-to-many relationship). + /// Key names are restricted to alpha-numeric characters and the '_' character. + /// Both keys and values cannot exceed 255 characters in length. Key-value tags are searchable by exact match only. + /// To replace all values associated to one key use RemoveKeyValueTags then AddKeyValueTag. + /// public Editor AddKeyValueTag(string key, string value) { - if (KeyValueTags == null) KeyValueTags = new Dictionary(); - KeyValueTags.Add(key, value); + if (KeyValueTags == null) + KeyValueTags = new Dictionary>(); + + if ( KeyValueTags.TryGetValue( key, out var list ) ) + list.Add( value ); + else + KeyValueTags[key] = new List() { value }; + + return this; + } + + /// + /// Removes a key and all values associated to it. + /// You can remove up to 100 keys per item update. + /// If you need remove more tags than that you'll need to make subsequent item updates. + /// + public Editor RemoveKeyValueTags( string key ) + { + if ( KeyValueTagsToRemove == null ) + KeyValueTagsToRemove = new HashSet(); + + KeyValueTagsToRemove.Add( key ); return this; } @@ -156,11 +184,19 @@ namespace Steamworks.Ugc } } - if (KeyValueTags != null && KeyValueTags.Count > 0) + if ( KeyValueTagsToRemove != null) { - foreach (var keyValueTag in KeyValueTags) + foreach ( var key in KeyValueTagsToRemove ) + SteamUGC.Internal.RemoveItemKeyValueTags( handle, key ); + } + + if ( KeyValueTags != null ) + { + foreach ( var keyWithValues in KeyValueTags ) { - SteamUGC.Internal.AddItemKeyValueTag(handle, keyValueTag.Key, keyValueTag.Value); + var key = keyWithValues.Key; + foreach ( var value in keyWithValues.Value ) + SteamUGC.Internal.AddItemKeyValueTag( handle, key, value ); } } diff --git a/Facepunch.Steamworks/Structs/UgcItem.cs b/Facepunch.Steamworks/Structs/UgcItem.cs index 640a0a4..87457e6 100644 --- a/Facepunch.Steamworks/Structs/UgcItem.cs +++ b/Facepunch.Steamworks/Structs/UgcItem.cs @@ -39,6 +39,11 @@ namespace Steamworks.Ugc /// public string[] Tags { get; internal set; } + /// + /// A dictionary of key value tags for this item, only available from queries WithKeyValueTags(true) + /// + public Dictionary KeyValueTags { get; internal set; } + /// /// App Id of the app that created this item /// diff --git a/Facepunch.Steamworks/Structs/UgcQuery.cs b/Facepunch.Steamworks/Structs/UgcQuery.cs index d448224..ba676ec 100644 --- a/Facepunch.Steamworks/Structs/UgcQuery.cs +++ b/Facepunch.Steamworks/Structs/UgcQuery.cs @@ -148,7 +148,8 @@ namespace Steamworks.Ugc Handle = result.Value.Handle, ResultCount = (int) result.Value.NumResultsReturned, TotalCount = (int)result.Value.TotalMatchingResults, - CachedData = result.Value.CachedData + CachedData = result.Value.CachedData, + ReturnsKeyValueTags = WantsReturnKeyValueTags ?? false, }; } @@ -241,7 +242,9 @@ namespace Steamworks.Ugc bool? WantsReturnOnlyIDs; public QueryType WithOnlyIDs(bool b) { WantsReturnOnlyIDs = b; return this; } bool? WantsReturnKeyValueTags; - public QueryType WithKeyValueTag(bool b) { WantsReturnKeyValueTags = b; return this; } + public QueryType WithKeyValueTags(bool b) { WantsReturnKeyValueTags = b; return this; } + [Obsolete( "Renamed to WithKeyValueTags" )] + public QueryType WithKeyValueTag(bool b) { WantsReturnKeyValueTags = b; return this; } bool? WantsReturnLongDescription; public QueryType WithLongDescription(bool b) { WantsReturnLongDescription = b; return this; } bool? WantsReturnMetadata; diff --git a/Facepunch.Steamworks/Structs/UgcResultPage.cs b/Facepunch.Steamworks/Structs/UgcResultPage.cs index 77044af..f2c45c3 100644 --- a/Facepunch.Steamworks/Structs/UgcResultPage.cs +++ b/Facepunch.Steamworks/Structs/UgcResultPage.cs @@ -12,6 +12,7 @@ namespace Steamworks.Ugc public bool CachedData; + internal bool ReturnsKeyValueTags; public IEnumerable Entries { get @@ -43,9 +44,21 @@ namespace Steamworks.Ugc item.PreviewImageUrl = preview; } + if ( ReturnsKeyValueTags ) + { + var keyValueTagsCount = SteamUGC.Internal.GetQueryUGCNumKeyValueTags( Handle, i ); + + item.KeyValueTags = new Dictionary( (int)keyValueTagsCount ); + for ( uint j = 0; j < keyValueTagsCount; j++ ) + { + string key, value; + if ( SteamUGC.Internal.GetQueryUGCKeyValueTag( Handle, i, j, out key, out value ) ) + item.KeyValueTags[key] = value; + } + } + // TODO GetQueryUGCAdditionalPreview // TODO GetQueryUGCChildren - // TODO GetQueryUGCKeyValueTag // TODO GetQueryUGCMetadata