Files
sbox-public/engine/Sandbox.Engine/Game/Services/Stats/Stats.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

150 lines
4.4 KiB
C#

using System.Runtime.CompilerServices;
using System.Threading;
namespace Sandbox.Services;
/// <summary>
/// Allows access to stats for the current game. Stats are defined by the game's author
/// and can be used to track anything from player actions to performance metrics. They are
/// how you submit data to leaderboards.
/// </summary>
public static partial class Stats
{
/// <summary>
/// Send any pending stats to the backend. Don't wait for confirmation of ingestiom, fire and forget.
/// </summary>
[MethodImpl( MethodImplOptions.NoInlining )]
public static Task FlushAsync( CancellationToken token = default )
{
var package = Application.GameIdent;
if ( package is null )
return Task.CompletedTask;
return Api.Stats.FlushWithBookmarkAsync( package, false, token );
}
/// <summary>
/// Send any pending stats to the backend. Don't wait for confirmation of ingestiom, fire and forget.
/// </summary>
[MethodImpl( MethodImplOptions.NoInlining )]
public static void Flush()
{
var package = Application.GameIdent;
if ( package is null )
return;
_ = Api.Stats.FlushWithBookmarkAsync( package, false, default );
}
/// <summary>
/// Send any pending stats to the backend, will wait until they're available for query before finishing.
/// </summary>
[MethodImpl( MethodImplOptions.NoInlining )]
public static Task FlushAndWaitAsync( CancellationToken token = default )
{
var package = Application.GameIdent;
if ( package is null )
return Task.CompletedTask;
return Api.Stats.FlushWithBookmarkAsync( package, true, token );
}
[MethodImpl( MethodImplOptions.NoInlining )]
public static void Increment( string name, double amount )
{
var package = Application.GameIdent;
if ( package is null ) return;
Api.Stats.AddIncrement( package, name, amount, null );
var localStats = Stats.GetLocalPlayerStats( package );
localStats?.Predict( name, amount );
}
[MethodImpl( MethodImplOptions.NoInlining ), Obsolete]
public static void Increment( string name, double amount, string context, object data = default ) => Increment( name, amount );
[MethodImpl( MethodImplOptions.NoInlining )]
public static void Increment( string name, double amount, Dictionary<string, object> data )
{
var package = Application.GameIdent;
if ( package is null ) return;
Api.Stats.AddIncrement( package, name, amount, GetObjectDictionary( data ) );
var localStats = Stats.GetLocalPlayerStats( package );
localStats?.Predict( name, amount );
}
private static Dictionary<string, object> GetObjectDictionary( object data )
{
if ( data is null )
return null;
if ( data is Dictionary<string, object> o )
{
return o;
}
try
{
var json = System.Text.Json.JsonSerializer.Serialize( data );
return System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>( json );
}
catch ( System.Exception e )
{
Log.Warning( e, $"Couldn't encode stat data ({e.Message})" );
return null;
}
}
[MethodImpl( MethodImplOptions.NoInlining )]
public static void SetValue( string name, double amount, string context = null, object data = null )
{
var package = Application.GameIdent;
if ( package is null ) return;
Api.Stats.SetValue( package, name, amount, GetObjectDictionary( data ) );
var localStats = Stats.GetLocalPlayerStats( package );
localStats?.Predict( name, amount );
}
[MethodImpl( MethodImplOptions.NoInlining )]
public static void SetValue( string name, double amount, Dictionary<string, object> data )
{
var package = Application.GameIdent;
if ( package is null ) return;
Api.Stats.SetValue( package, name, amount, GetObjectDictionary( data ) );
var localStats = Stats.GetLocalPlayerStats( package );
localStats?.Predict( name, amount );
}
internal static void RPC_StatsIncrement( string package, string name, double amount, string data )
{
Dictionary<string, object> oData = null;
if ( !string.IsNullOrWhiteSpace( data ) )
{
oData = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>( data );
}
Api.Stats.AddIncrement( package, name, amount, oData );
}
internal static void RPC_StatsSetValue( string package, string name, double amount, string data )
{
Dictionary<string, object> oData = null;
if ( !string.IsNullOrWhiteSpace( data ) )
{
oData = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>( data );
}
Api.Stats.SetValue( package, name, amount, oData );
}
}