diff --git a/Facepunch.Steamworks.Test/UserStatsTest.cs b/Facepunch.Steamworks.Test/UserStatsTest.cs index 6d0b2c9..8021ac8 100644 --- a/Facepunch.Steamworks.Test/UserStatsTest.cs +++ b/Facepunch.Steamworks.Test/UserStatsTest.cs @@ -4,11 +4,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Steamworks.Data; namespace Steamworks { [TestClass] [DeploymentItem( "steam_api64.dll" )] + [DeploymentItem( "steam_appid.txt" )] public class UserStatsTest { [TestMethod] @@ -151,6 +153,42 @@ namespace Steamworks } } + [TestMethod] + public void GetStatInt() + { + var startups = new Stat( "GMA_X_STARTUPS_STAT" ); + Console.WriteLine( $"{startups.Name} {startups.GetInt()} times" ); + Console.WriteLine( $"{startups.Name} {startups.GetFloat()} times" ); + + Assert.AreNotEqual( 0, startups.GetInt() ); + } + + [TestMethod] + public async Task GetStatGlobalInt() + { + var startups = new Stat( "GMA_X_STARTUPS_STAT" ); + await startups.GetGlobalIntDays( 5 ); + + await Task.Delay( 3000 ); + + var totalStartups = startups.GetGlobalInt(); + Assert.AreNotEqual( 0, totalStartups ); + Console.WriteLine( $"Garry's Mod has been started {totalStartups} times" ); + } + + [TestMethod] + public async Task GetStatGlobalHistoryInt() + { + var startups = new Stat( "GMA_X_STARTUPS_STAT" ); + + var history = await startups.GetGlobalIntDays( 60 ); + + for( int i=0; i< history.Length; i++ ) + { + Console.WriteLine( $"{i} : {history[i]}" ); + } + } + } } diff --git a/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll b/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll index 515d878..ba15291 100644 Binary files a/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll and b/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll differ diff --git a/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll b/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll index 85806bb..39bd4f3 100644 Binary files a/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll and b/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll differ diff --git a/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll b/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll index ee54d97..a4db1c1 100644 Binary files a/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll and b/Facepunch.Steamworks.Test/bin/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll differ diff --git a/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll new file mode 100644 index 0000000..ba15291 Binary files /dev/null and b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll differ diff --git a/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll new file mode 100644 index 0000000..39bd4f3 Binary files /dev/null and b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll differ diff --git a/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll new file mode 100644 index 0000000..a4db1c1 Binary files /dev/null and b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll differ diff --git a/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll new file mode 100644 index 0000000..c426bea Binary files /dev/null and b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll differ diff --git a/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.TestFramework.dll b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.TestFramework.dll new file mode 100644 index 0000000..d4afc5e Binary files /dev/null and b/Facepunch.Steamworks.Test/bin/x64/Debug/Microsoft.VisualStudio.TestPlatform.TestFramework.dll differ diff --git a/Facepunch.Steamworks.Test/bin/x64/Debug/Newtonsoft.Json.dll b/Facepunch.Steamworks.Test/bin/x64/Debug/Newtonsoft.Json.dll new file mode 100644 index 0000000..5523f5c Binary files /dev/null and b/Facepunch.Steamworks.Test/bin/x64/Debug/Newtonsoft.Json.dll differ diff --git a/Facepunch.Steamworks.Test/bin/x64/Debug/steam_api64.dll b/Facepunch.Steamworks.Test/bin/x64/Debug/steam_api64.dll new file mode 100644 index 0000000..328dade Binary files /dev/null and b/Facepunch.Steamworks.Test/bin/x64/Debug/steam_api64.dll differ diff --git a/Facepunch.Steamworks/Generated/Interfaces/ISteamUserStats.cs b/Facepunch.Steamworks/Generated/Interfaces/ISteamUserStats.cs index a86e5df..4654900 100644 --- a/Facepunch.Steamworks/Generated/Interfaces/ISteamUserStats.cs +++ b/Facepunch.Steamworks/Generated/Interfaces/ISteamUserStats.cs @@ -536,24 +536,24 @@ namespace Steamworks #region FunctionMeta [UnmanagedFunctionPointer( CallingConvention.ThisCall )] - private delegate int GetGlobalStatHistoryDelegate( IntPtr self, string pchStatName, ref long pData, uint cubData ); + private delegate int GetGlobalStatHistoryDelegate( IntPtr self, string pchStatName, [In,Out] long[] pData, uint cubData ); private GetGlobalStatHistoryDelegate GetGlobalStatHistoryDelegatePointer; #endregion - internal int GetGlobalStatHistory( string pchStatName, ref long pData, uint cubData ) + internal int GetGlobalStatHistory( string pchStatName, [In,Out] long[] pData, uint cubData ) { - return GetGlobalStatHistoryDelegatePointer( Self, pchStatName, ref pData, cubData ); + return GetGlobalStatHistoryDelegatePointer( Self, pchStatName, pData, cubData ); } #region FunctionMeta [UnmanagedFunctionPointer( CallingConvention.ThisCall )] - private delegate int GetGlobalStatHistory2Delegate( IntPtr self, string pchStatName, ref double pData, uint cubData ); + private delegate int GetGlobalStatHistory2Delegate( IntPtr self, string pchStatName, [In,Out] double[] pData, uint cubData ); private GetGlobalStatHistory2Delegate GetGlobalStatHistory2DelegatePointer; #endregion - internal int GetGlobalStatHistory2( string pchStatName, ref double pData, uint cubData ) + internal int GetGlobalStatHistory2( string pchStatName, [In,Out] double[] pData, uint cubData ) { - return GetGlobalStatHistory2DelegatePointer( Self, pchStatName, ref pData, cubData ); + return GetGlobalStatHistory2DelegatePointer( Self, pchStatName, pData, cubData ); } } diff --git a/Facepunch.Steamworks/Structs/Stat.cs b/Facepunch.Steamworks/Structs/Stat.cs new file mode 100644 index 0000000..2e6d4fe --- /dev/null +++ b/Facepunch.Steamworks/Structs/Stat.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Steamworks.Data +{ + public struct Stat + { + public string Name { get; internal set; } + public SteamId UserId { get; internal set; } + + public Stat( string name ) + { + Name = name; + UserId = 0; + } + + public Stat( string name, SteamId user ) + { + Name = name; + UserId = user; + } + + internal void LocalUserOnly( [CallerMemberName] string caller = null ) + { + if ( UserId == 0 ) return; + throw new System.Exception( $"Stat.{caller} can only be called for the local user" ); + } + + public double GetGlobalFloat() + { + double val = 0.0; + + if ( SteamUserStats.Internal.GetGlobalStat2( Name, ref val ) ) + return val; + + return 0; + } + + public long GetGlobalInt() + { + long val = 0; + SteamUserStats.Internal.GetGlobalStat( Name, ref val ); + return val; + } + + public async Task GetGlobalIntDays( int days ) + { + var result = await SteamUserStats.Internal.RequestGlobalStats( days ); + if ( result?.Result != Result.OK ) return null; + + var r = new long[days]; + + var rows = SteamUserStats.Internal.GetGlobalStatHistory( Name, r, (uint) r.Length ); + + if ( days != rows ) + r = r.Take( rows ).ToArray(); + + return r; + } + + public async Task GetGlobalFloatDays( int days ) + { + var result = await SteamUserStats.Internal.RequestGlobalStats( days ); + if ( result?.Result != Result.OK ) return null; + + var r = new double[days]; + + var rows = SteamUserStats.Internal.GetGlobalStatHistory2( Name, r, (uint)r.Length ); + + if ( days != rows ) + r = r.Take( rows ).ToArray(); + + return r; + } + + public float GetFloat() + { + float val = 0.0f; + + if ( UserId > 0 ) + { + SteamUserStats.Internal.GetUserStat2( UserId, Name, ref val ); + } + else + { + SteamUserStats.Internal.GetStat2( Name, ref val ); + } + + return 0; + } + + public int GetInt() + { + int val = 0; + + if ( UserId > 0 ) + { + SteamUserStats.Internal.GetUserStat( UserId, Name, ref val ); + } + else + { + SteamUserStats.Internal.GetStat( Name, ref val ); + } + + return val; + } + + public bool Set( int val ) + { + LocalUserOnly(); + return SteamUserStats.Internal.SetStat( Name, val ); + } + + public bool Set( float val ) + { + LocalUserOnly(); + return SteamUserStats.Internal.SetStat2( Name, val ); + } + + public bool UpdateAverageRate( float count, float sessionlength ) + { + LocalUserOnly(); + return SteamUserStats.Internal.UpdateAvgRateStat( Name, count, sessionlength ); + } + + public bool Store() + { + LocalUserOnly(); + return SteamUserStats.Internal.StoreStats(); + } + } +} \ No newline at end of file diff --git a/Generator/CodeWriter/ClassVTable.cs b/Generator/CodeWriter/ClassVTable.cs index 0775a8e..a7a2529 100644 --- a/Generator/CodeWriter/ClassVTable.cs +++ b/Generator/CodeWriter/ClassVTable.cs @@ -71,8 +71,14 @@ namespace Generator private void WriteFunction( CodeParser.Class clss, CodeParser.Class.Function func ) { var returnType = BaseType.Parse( func.ReturnType ); + returnType.Func = func.Name; - var args = func.Arguments.Select( x => BaseType.Parse( x.Value, x.Key ) ).ToArray(); + var args = func.Arguments.Select( x => + { + var bt = BaseType.Parse( x.Value, x.Key ); + bt.Func = func.Name; + return bt; + } ).ToArray(); var argstr = string.Join( ", ", args.Select( x => x.AsArgument() ) ); var delegateargstr = string.Join( ", ", args.Select( x => x.AsArgument() ) ); diff --git a/Generator/CodeWriter/Types/BaseType.cs b/Generator/CodeWriter/Types/BaseType.cs index 0bbedfb..61db8d0 100644 --- a/Generator/CodeWriter/Types/BaseType.cs +++ b/Generator/CodeWriter/Types/BaseType.cs @@ -11,6 +11,8 @@ internal class BaseType public virtual string TypeName => $"{NativeType}"; public virtual string TypeNameFrom => TypeName; + public string Func; + public static BaseType Parse( string type, string varname = null ) { type = Cleanup.ConvertType( type ); @@ -63,6 +65,7 @@ internal class BaseType if ( VarName == "pScoreDetails" ) return true; if ( VarName == "prgUsers" ) return true; if ( VarName == "pDetails" ) return true; + if ( VarName == "pData" && NativeType.EndsWith( "*" ) && Func.StartsWith( "GetGlobalStatHistory" ) ) return true; if ( NativeType.EndsWith( "**" ) ) return true; if ( NativeType.EndsWith( "*" ) )