diff --git a/Facepunch.Steamworks/Client.cs b/Facepunch.Steamworks/Client.cs
index e21ea95..954a538 100644
--- a/Facepunch.Steamworks/Client.cs
+++ b/Facepunch.Steamworks/Client.cs
@@ -51,6 +51,8 @@ namespace Facepunch.Steamworks
public Voice Voice { get; private set; }
public ServerList ServerList { get; private set; }
public App App { get; private set; }
+ public Achievements Achievements { get; private set; }
+ public Stats Stats { get; private set; }
public Client( uint appId )
{
@@ -77,10 +79,11 @@ namespace Facepunch.Steamworks
Voice = new Voice( this );
ServerList = new ServerList( this );
App = new App( this );
+ Stats = new Stats( this );
+ Achievements = new Achievements( this );
Workshop.friends = Friends;
-
//
// Cache common, unchanging info
//
@@ -145,6 +148,18 @@ namespace Facepunch.Steamworks
App = null;
}
+ if ( Stats != null )
+ {
+ Stats.Dispose();
+ Stats = null;
+ }
+
+ if ( Achievements != null )
+ {
+ Achievements.Dispose();
+ Achievements = null;
+ }
+
base.Dispose();
}
diff --git a/Facepunch.Steamworks/Client/Achievements.cs b/Facepunch.Steamworks/Client/Achievements.cs
new file mode 100644
index 0000000..ae43092
--- /dev/null
+++ b/Facepunch.Steamworks/Client/Achievements.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Facepunch.Steamworks
+{
+ public class Achievements : IDisposable
+ {
+ internal Client client;
+
+ public Achievement[] All { get; private set; }
+
+ internal Achievements( Client c )
+ {
+ client = c;
+ Refresh();
+ }
+
+ public void Refresh()
+ {
+ All = Enumerable.Range( 0, (int)client.native.userstats.GetNumAchievements() )
+ .Select( x => new Achievement( client, x ) )
+ .ToArray();
+ }
+
+ public void Dispose()
+ {
+ client = null;
+ }
+
+ }
+
+ public class Achievement
+ {
+ private Client client;
+
+ public string Id { get; private set; }
+ public string Name { get; private set; }
+ public string Description { get; private set; }
+
+ ///
+ /// True if unlocked
+ ///
+ public bool State { get; private set; }
+
+ ///
+ /// Should hold the unlock time if State is true
+ ///
+ public DateTime UnlockTime { get; private set; }
+
+ ///
+ /// If this achievement is linked to a stat this will return the progress.
+ ///
+ public float Percentage
+ {
+ get
+ {
+ if ( State )
+ return 1;
+
+ float pct = 0;
+
+ if ( !client.native.userstats.GetAchievementAchievedPercent( Id, out pct ) )
+ return -1.0f;
+
+ return pct;
+ }
+ }
+
+ public Achievement( Client client, int index )
+ {
+ this.client = client;
+
+ Id = client.native.userstats.GetAchievementName( (uint) index );
+ Name = client.native.userstats.GetAchievementDisplayAttribute( Id, "name" );
+ Description = client.native.userstats.GetAchievementDisplayAttribute( Id, "desc" );
+
+ Refresh();
+ }
+
+ ///
+ /// Make this achievement earned
+ ///
+ public bool Trigger()
+ {
+ State = true;
+ UnlockTime = DateTime.Now;
+
+ return client.native.userstats.SetAchievement( Id );
+ }
+
+ ///
+ /// Reset this achievement to not achieved
+ ///
+ public bool Reset()
+ {
+ State = false;
+ UnlockTime = DateTime.Now;
+
+ return client.native.userstats.ClearAchievement( Id );
+ }
+
+ ///
+ /// Refresh the unlock state. You shouldn't need to call this manually
+ /// but it's here if you have to for some reason.
+ ///
+ public void Refresh()
+ {
+ bool state = false;
+ uint unlockTime;
+
+ State = false;
+
+ if ( client.native.userstats.GetAchievementAndUnlockTime( Id, ref state, out unlockTime ) )
+ {
+ State = state;
+ UnlockTime = Utility.Epoch.ToDateTime( unlockTime );
+ }
+ }
+ }
+
+}
diff --git a/Facepunch.Steamworks/Client/Stats.cs b/Facepunch.Steamworks/Client/Stats.cs
index 8167fbc..2a3bfc6 100644
--- a/Facepunch.Steamworks/Client/Stats.cs
+++ b/Facepunch.Steamworks/Client/Stats.cs
@@ -5,29 +5,15 @@ using System.Text;
namespace Facepunch.Steamworks
{
- public partial class Client : IDisposable
- {
- Stats _stats;
-
- public Stats Stats
- {
- get
- {
- if ( _stats == null )
- _stats = new Stats( this );
-
- return _stats;
- }
- }
- }
-
- public class Stats
+ public class Stats : IDisposable
{
internal Client client;
internal Stats( Client c )
{
client = c;
+
+ UpdateStats();
}
public void UpdateStats()
@@ -70,5 +56,9 @@ namespace Facepunch.Steamworks
return data;
}
+ public void Dispose()
+ {
+ client = null;
+ }
}
}