using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Steamworks.Data { /// /// Represents a Steam Achievement. /// public struct Achievement { internal string Value; public Achievement( string name ) { Value = name; } public override string ToString() => Value; /// /// Gets whether or not the achievement has been unlocked. /// public bool State { get { var state = false; SteamUserStats.Internal?.GetAchievement( Value, ref state ); return state; } } /// /// Gets the identifier of the achievement. This is the "API Name" on Steamworks. /// public string Identifier => Value; /// /// Gets the display name of the achievement. /// public string? Name => SteamUserStats.Internal?.GetAchievementDisplayAttribute( Value, "name" ); /// /// Gets the description of the achievement. /// public string? Description => SteamUserStats.Internal?.GetAchievementDisplayAttribute( Value, "desc" ); /// /// If is , this value represents the time that the achievement was unlocked. /// public DateTime? UnlockTime { get { var state = false; uint time = 0; if ( SteamUserStats.Internal is null || !SteamUserStats.Internal.GetAchievementAndUnlockTime( Value, ref state, ref time ) || !state ) return null; return Epoch.ToDateTime( time ); } } /// /// Gets the icon of the achievement. This can return a null image even though the image exists if the image /// hasn't been downloaded by Steam yet. You should use if you want to wait for the image to be downloaded. /// public Image? GetIcon() { if (SteamUserStats.Internal is null) { return null; } return SteamUtils.GetImage( SteamUserStats.Internal.GetAchievementIcon( Value ) ); } /// /// Gets the icon of the achievement, yielding until the icon is received or the is reached. /// /// The timeout in milliseconds before the request will be canceled. Defaults to 5000. public async Task GetIconAsync( int timeout = 5000 ) { if (SteamUserStats.Internal is null) { return null; } var i = SteamUserStats.Internal.GetAchievementIcon( Value ); if ( i != 0 ) return SteamUtils.GetImage( i ); var ident = Identifier; bool gotCallback = false; void f( string x, int icon ) { if ( x != ident ) return; i = icon; gotCallback = true; } try { SteamUserStats.OnAchievementIconFetched += f; int waited = 0; while ( !gotCallback ) { await Task.Delay( 10 ); waited += 10; // Time out after x milliseconds if ( waited > timeout ) return null; } if ( i == 0 ) return null; return SteamUtils.GetImage( i ); } finally { SteamUserStats.OnAchievementIconFetched -= f; } } /// /// Gets a decimal (0-1) representing the global amount of users who have unlocked the specified achievement, or -1 if no data available. /// public float GlobalUnlocked { get { float pct = 0; if ( SteamUserStats.Internal is null || !SteamUserStats.Internal.GetAchievementAchievedPercent( Value, ref pct ) ) return -1.0f; return pct / 100.0f; } } /// /// Unlock this achievement. /// public bool Trigger( bool apply = true ) { if (SteamUserStats.Internal is null) { return false; } var r = SteamUserStats.Internal.SetAchievement( Value ); if ( apply && r ) { SteamUserStats.Internal.StoreStats(); } return r; } /// /// Reset this achievement to be locked. /// public bool Clear() { if (SteamUserStats.Internal is null) { return false; } return SteamUserStats.Internal.ClearAchievement( Value ); } } }