using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Facepunch.Steamworks.Data { public struct Achievement { internal string Value; public Achievement( string name ) { Value = name; } public override string ToString() => Value; /// /// True if unlocked /// public bool State { get { var state = false; SteamUserStats.Internal.GetAchievement( Value, ref state ); return state; } } public string Identifier => Value; public string Name => SteamUserStats.Internal.GetAchievementDisplayAttribute( Value, "name" ); public string Description => SteamUserStats.Internal.GetAchievementDisplayAttribute( Value, "desc" ); /// /// Should hold the unlock time if State is true /// public DateTime? UnlockTime { get { var state = false; uint time = 0; if ( !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 can use GetIconAsync if you want to wait for the image to be downloaded. /// public Image? GetIcon() { return SteamUtils.GetImage( SteamUserStats.Internal.GetAchievementIcon( Value ) ); } /// /// Gets the icon of the achievement, waits for it to load if we have to /// public async Task GetIconAsync( int timeout = 5000 ) { 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; } } /// /// Returns the fraction (0-1) of users who have unlocked the specified achievement, or -1 if no data available. /// public float GlobalUnlocked { get { float pct = 0; if ( !SteamUserStats.Internal.GetAchievementAchievedPercent( Value, ref pct ) ) return -1.0f; return pct / 100.0f; } } /// /// Make this achievement earned /// public bool Trigger( bool apply = true ) { var r = SteamUserStats.Internal.SetAchievement( Value ); if ( apply && r ) { SteamUserStats.Internal.StoreStats(); } return r; } /// /// Reset this achievement to not achieved /// public bool Clear() { return SteamUserStats.Internal.ClearAchievement( Value ); } } }