38f1ddb...178a853: v0.8.9.1, removed content folder
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SteamNative;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public class Achievements : IDisposable
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
public Achievement[] All { get; private set; }
|
||||
|
||||
public event Action OnUpdated;
|
||||
public event Action<Achievement> OnAchievementStateChanged;
|
||||
|
||||
private List<Achievement> unlockedRecently = new List<Achievement>();
|
||||
|
||||
internal Achievements( Client c )
|
||||
{
|
||||
client = c;
|
||||
|
||||
All = new Achievement[0];
|
||||
c.RegisterCallback<UserStatsReceived_t>( UserStatsReceived );
|
||||
c.RegisterCallback<UserStatsStored_t>( UserStatsStored );
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
var old = All;
|
||||
|
||||
All = Enumerable.Range( 0, (int)client.native.userstats.GetNumAchievements() )
|
||||
.Select( x =>
|
||||
{
|
||||
if ( old != null )
|
||||
{
|
||||
var name = client.native.userstats.GetAchievementName( (uint)x );
|
||||
var found = old.FirstOrDefault( y => y.Id == name );
|
||||
if ( found != null )
|
||||
{
|
||||
if ( found.Refresh() )
|
||||
{
|
||||
unlockedRecently.Add( found );
|
||||
}
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return new Achievement( client, x );
|
||||
} )
|
||||
.ToArray();
|
||||
|
||||
foreach ( var i in unlockedRecently )
|
||||
{
|
||||
OnUnlocked( i );
|
||||
}
|
||||
|
||||
unlockedRecently.Clear();
|
||||
}
|
||||
|
||||
internal void OnUnlocked( Achievement a )
|
||||
{
|
||||
OnAchievementStateChanged?.Invoke( a );
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
client = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find an achievement by name. Will be null if not found, or not ready.
|
||||
/// </summary>
|
||||
public Achievement Find( string identifier )
|
||||
{
|
||||
return All.FirstOrDefault( x => x.Id == identifier );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlock an achievement by identifier. If apply is true this will happen as expected
|
||||
/// and the achievement overlay will popup etc. If it's false then you'll have to manually
|
||||
/// call Stats.StoreStats() to actually trigger it.
|
||||
/// </summary>
|
||||
public bool Trigger( string identifier, bool apply = true )
|
||||
{
|
||||
var a = Find( identifier );
|
||||
if ( a == null ) return false;
|
||||
|
||||
return a.Trigger( apply );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset an achievement by identifier
|
||||
/// </summary>
|
||||
public bool Reset( string identifier )
|
||||
{
|
||||
return client.native.userstats.ClearAchievement( identifier );
|
||||
}
|
||||
|
||||
private void UserStatsReceived( UserStatsReceived_t stats )
|
||||
{
|
||||
if ( stats.GameID != client.AppId ) return;
|
||||
|
||||
Refresh();
|
||||
|
||||
OnUpdated?.Invoke();
|
||||
}
|
||||
|
||||
private void UserStatsStored( UserStatsStored_t stats )
|
||||
{
|
||||
if ( stats.GameID != client.AppId ) return;
|
||||
|
||||
Refresh();
|
||||
|
||||
OnUpdated?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public class Achievement
|
||||
{
|
||||
private Client client;
|
||||
|
||||
public string Id { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public string Description { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if unlocked
|
||||
/// </summary>
|
||||
public bool State { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should hold the unlock time if State is true
|
||||
/// </summary>
|
||||
public DateTime UnlockTime { get; private set; }
|
||||
|
||||
private int iconId { get; set; } = -1;
|
||||
private int refreshCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the percentage of users who have unlocked the specified achievement, or -1 if no data available.
|
||||
/// </summary>
|
||||
public float GlobalUnlockedPercentage
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( State )
|
||||
return 1;
|
||||
|
||||
float pct = 0;
|
||||
|
||||
if ( !client.native.userstats.GetAchievementAchievedPercent( Id, out pct ) )
|
||||
return -1.0f;
|
||||
|
||||
return pct;
|
||||
}
|
||||
}
|
||||
|
||||
private Image _icon;
|
||||
|
||||
public Image Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( iconId <= 0 ) return null;
|
||||
|
||||
if ( _icon == null )
|
||||
{
|
||||
_icon = new Image();
|
||||
_icon.Id = iconId;
|
||||
}
|
||||
|
||||
if ( _icon.IsLoaded )
|
||||
return _icon;
|
||||
|
||||
if ( !_icon.TryLoad( client.native.utils ) )
|
||||
return null;
|
||||
|
||||
return _icon;
|
||||
}
|
||||
}
|
||||
|
||||
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" );
|
||||
|
||||
iconId = client.native.userstats.GetAchievementIcon( Id );
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make this achievement earned
|
||||
/// </summary>
|
||||
public bool Trigger( bool apply = true )
|
||||
{
|
||||
if ( State )
|
||||
return false;
|
||||
|
||||
State = true;
|
||||
UnlockTime = DateTime.Now;
|
||||
|
||||
var r = client.native.userstats.SetAchievement( Id );
|
||||
|
||||
if ( apply )
|
||||
{
|
||||
client.Stats.StoreStats();
|
||||
}
|
||||
|
||||
client.Achievements.OnUnlocked( this );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset this achievement to not achieved
|
||||
/// </summary>
|
||||
public bool Reset()
|
||||
{
|
||||
State = false;
|
||||
UnlockTime = DateTime.Now;
|
||||
|
||||
return client.native.userstats.ClearAchievement( Id );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh the unlock state. You shouldn't need to call this manually
|
||||
/// but it's here if you have to for some reason. Retuns true if state changed (meaning, probably unlocked)
|
||||
/// </summary>
|
||||
public bool Refresh()
|
||||
{
|
||||
bool previousState = State;
|
||||
|
||||
bool state = false;
|
||||
uint unlockTime;
|
||||
|
||||
State = false;
|
||||
|
||||
if ( client.native.userstats.GetAchievementAndUnlockTime( Id, ref state, out unlockTime ) )
|
||||
{
|
||||
State = state;
|
||||
UnlockTime = Utility.Epoch.ToDateTime( unlockTime );
|
||||
}
|
||||
|
||||
refreshCount++;
|
||||
|
||||
if ( previousState != State && refreshCount > 1 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user