From ea97de9c02bfc54d18571aac8c1738cc3c5fd240 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Mon, 6 May 2019 20:46:11 +0100 Subject: [PATCH] Tons of extra UGCItem fields --- Facepunch.Steamworks/Structs/UgcItem.cs | 151 +++++++++++++++--- Facepunch.Steamworks/Structs/UgcResultPage.cs | 41 ++++- 2 files changed, 171 insertions(+), 21 deletions(-) diff --git a/Facepunch.Steamworks/Structs/UgcItem.cs b/Facepunch.Steamworks/Structs/UgcItem.cs index 63d1715..41ced44 100644 --- a/Facepunch.Steamworks/Structs/UgcItem.cs +++ b/Facepunch.Steamworks/Structs/UgcItem.cs @@ -10,23 +10,83 @@ namespace Steamworks.Ugc { public struct Item { - internal enum ItemState : int - { - None = 0, - Subscribed = 1, - LegacyItem = 2, - Installed = 4, - NeedsUpdate = 8, - Downloading = 16, - DownloadPending = 32, - } + internal SteamUGCDetails_t details; - public PublishedFileId Id { get; internal set; } + /// + /// The actual ID of this file + /// + public PublishedFileId Id => details.PublishedFileId; - public string Title { get; internal set; } - public string Description { get; internal set; } + /// + /// The given title of this item + /// + public string Title => details.Title; + + /// + /// The description of this item, in your local language if available + /// + public string Description => details.Description; + + /// + /// A list of tags for this item, all lowercase + /// public string[] Tags { get; internal set; } + /// + /// App Id of the app that created this item + /// + public AppId CreatorApp => details.CreatorAppID; + + /// + /// App Id of the app that will consume this item. + /// + public AppId ConsumerApp => details.ConsumerAppID; + + /// + /// User who created this content + /// + public Friend Owner => new Friend( details.SteamIDOwner ); + + /// + /// The bayesian average for up votes / total votes, between [0,1] + /// + public float Score => details.Score; + + /// + /// Time when the published item was created + /// + public DateTime Created => Epoch.ToDateTime( details.TimeCreated ); + + /// + /// Time when the published item was last updated + /// + public DateTime Updated => Epoch.ToDateTime( details.TimeUpdated ); + + /// + /// True if this is publically visible + /// + public bool IsPublic => details.Visibility == RemoteStoragePublishedFileVisibility.Public; + + /// + /// True if this item is only visible by friends of the creator + /// + public bool IsFriendsOnly => details.Visibility == RemoteStoragePublishedFileVisibility.FriendsOnly; + + /// + /// True if this is only visible to the creator + /// + public bool IsPrivate => details.Visibility == RemoteStoragePublishedFileVisibility.Private; + + /// + /// True if this item has been banned + /// + public bool IsBanned => details.Banned; + + /// + /// Whether the developer of this app has specifically flagged this item as accepted in the Workshop + /// + public bool IsAcceptedForUse => details.AcceptedForUse; + public bool IsInstalled => (State & ItemState.Installed) == ItemState.Installed; public bool IsDownloading => (State & ItemState.Downloading) == ItemState.Downloading; public bool IsDownloadPending => (State & ItemState.DownloadPending) == ItemState.DownloadPending; @@ -47,6 +107,9 @@ public string Directory } } + /// + /// Start downloading this item + /// public bool Download( bool highPriority = false ) { return SteamUGC.Internal.DownloadItem( Id, highPriority ); @@ -66,13 +129,8 @@ internal static Item From( SteamUGCDetails_t details ) { var d = new Item { - Id = details.PublishedFileId, - // FileType = details.FileType, - - Title = details.Title, - Description = details.Description, - Tags = details.Tags.Split( new[] { ',' }, StringSplitOptions.RemoveEmptyEntries ) - + details = details, + Tags = details.Tags.ToLower().Split( new[] { ',' }, StringSplitOptions.RemoveEmptyEntries ) }; return d; @@ -88,5 +146,58 @@ public bool HasTag( string find ) return Tags.Contains( find, StringComparer.OrdinalIgnoreCase ); } + /// + /// Allows the user to rate a workshop item up or down. + /// + public async Task Vote( bool up ) + { + var r = await SteamUGC.Internal.SetUserItemVote( Id, up ); + 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}"; + + /// + /// The URl to view this item's changelog + /// + public string ChangelogUrl => $"http://steamcommunity.com/sharedfiles/filedetails/changelog/{Id}"; + + /// + /// The URL to view the comments on this item + /// + public string CommentsUrl => $"http://steamcommunity.com/sharedfiles/filedetails/comments/{Id}"; + + /// + /// The URL to discuss this item + /// + public string DiscussUrl => $"http://steamcommunity.com/sharedfiles/filedetails/discussions/{Id}"; + + /// + /// The URL to view this items stats online + /// + public string StatsUrl => $"http://steamcommunity.com/sharedfiles/filedetails/stats/{Id}"; + + public ulong NumSubscriptions { get; internal set; } + public ulong NumFavorites { get; internal set; } + public ulong NumFollowers { get; internal set; } + public ulong NumUniqueSubscriptions { get; internal set; } + public ulong NumUniqueFavorites { get; internal set; } + public ulong NumUniqueFollowers { get; internal set; } + public ulong NumUniqueWebsiteViews { get; internal set; } + public ulong ReportScore { get; internal set; } + public ulong NumSecondsPlayed { get; internal set; } + public ulong NumPlaytimeSessions { get; internal set; } + public ulong NumComments { get; internal set; } + public ulong NumSecondsPlayedDuringTimePeriod { get; internal set; } + public ulong NumPlaytimeSessionsDuringTimePeriod { get; internal set; } + + /// + /// The URL to the preview image for this item + /// + public string PreviewUrl { get; internal set; } } + } \ No newline at end of file diff --git a/Facepunch.Steamworks/Structs/UgcResultPage.cs b/Facepunch.Steamworks/Structs/UgcResultPage.cs index 06f4f5f..764f522 100644 --- a/Facepunch.Steamworks/Structs/UgcResultPage.cs +++ b/Facepunch.Steamworks/Structs/UgcResultPage.cs @@ -16,17 +16,56 @@ public IEnumerable Entries { get { + var details = default( SteamUGCDetails_t ); for ( uint i=0; i< ResultCount; i++ ) { if ( SteamUGC.Internal.GetQueryUGCResult( Handle, i, ref details ) ) { - yield return Item.From( details ); + var item = Item.From( details ); + + item.NumSubscriptions = GetStat( i, ItemStatistic.NumSubscriptions ); + item.NumFavorites = GetStat( i, ItemStatistic.NumFavorites ); + item.NumFollowers = GetStat( i, ItemStatistic.NumFollowers ); + item.NumUniqueSubscriptions = GetStat( i, ItemStatistic.NumUniqueSubscriptions ); + item.NumUniqueFavorites = GetStat( i, ItemStatistic.NumUniqueFavorites ); + item.NumUniqueFollowers = GetStat( i, ItemStatistic.NumUniqueFollowers ); + item.NumUniqueWebsiteViews = GetStat( i, ItemStatistic.NumUniqueWebsiteViews ); + item.ReportScore = GetStat( i, ItemStatistic.ReportScore ); + item.NumSecondsPlayed = GetStat( i, ItemStatistic.NumSecondsPlayed ); + item.NumPlaytimeSessions = GetStat( i, ItemStatistic.NumPlaytimeSessions ); + item.NumComments = GetStat( i, ItemStatistic.NumComments ); + item.NumSecondsPlayedDuringTimePeriod = GetStat( i, ItemStatistic.NumSecondsPlayedDuringTimePeriod ); + item.NumPlaytimeSessionsDuringTimePeriod = GetStat( i, ItemStatistic.NumPlaytimeSessionsDuringTimePeriod ); + + var sb = Helpers.TakeStringBuilder(); + if ( SteamUGC.Internal.GetQueryUGCPreviewURL( Handle, i, sb, (uint)sb.Capacity ) ) + { + item.PreviewUrl = sb.ToString(); + } + + // TODO GetQueryUGCAdditionalPreview + // TODO GetQueryUGCChildren + // TODO GetQueryUGCKeyValueTag + // TODO GetQueryUGCMetadata + + + yield return item; } } } } + private ulong GetStat( uint index, ItemStatistic stat ) + { + ulong val = 0; + + if ( !SteamUGC.Internal.GetQueryUGCStatistic( Handle, index, stat, ref val ) ) + return 0; + + return val; + } + public void Dispose() { if ( Handle > 0 )