diff --git a/Facepunch.Steamworks.Test/Client/Leaderboard.cs b/Facepunch.Steamworks.Test/Client/Leaderboard.cs index 6de0efc..1eb6388 100644 --- a/Facepunch.Steamworks.Test/Client/Leaderboard.cs +++ b/Facepunch.Steamworks.Test/Client/Leaderboard.cs @@ -68,9 +68,6 @@ namespace Facepunch.Steamworks.Test Assert.IsFalse( board.IsError ); Assert.IsNotNull( board.Name ); - Console.WriteLine( $"Board name is \"{board.Name}\"" ); - Console.WriteLine( $"Board has \"{board.TotalEntries}\" entries" ); - board.AddScore( true, 86275309, 7, 8, 9 ); var done = false; @@ -79,7 +76,7 @@ namespace Facepunch.Steamworks.Test { Assert.IsTrue( success ); - foreach ( var entry in board.Results ) + foreach ( var entry in results ) { Console.WriteLine( $"{entry.GlobalRank}: {entry.SteamId} ({entry.Name}) with {entry.Score}" ); @@ -135,5 +132,40 @@ namespace Facepunch.Steamworks.Test client.Update(); } } + + [TestMethod] + public void AddScoresCallback() + { + using ( var client = new Steamworks.Client( 252490 ) ) + { + var board = client.GetLeaderboard( "TestLeaderboard", Steamworks.Client.LeaderboardSortMethod.Ascending, Steamworks.Client.LeaderboardDisplayType.Numeric ); + + while ( !board.IsValid ) + { + Thread.Sleep( 10 ); + client.Update(); + } + + Assert.IsTrue( board.IsValid ); + Assert.IsFalse( board.IsError ); + + var done = false; + + const int score = 5678; + + board.AddScore( false, score, null, ( success, result ) => + { + Assert.IsTrue( success ); + Assert.IsTrue( result.ScoreChanged ); + Assert.AreEqual( result.Score, score ); + } ); + + while ( !done ) + { + Thread.Sleep( 10 ); + client.Update(); + } + } + } } } \ No newline at end of file diff --git a/Facepunch.Steamworks/Client/Leaderboard.cs b/Facepunch.Steamworks/Client/Leaderboard.cs index 18edbd5..db4fce7 100644 --- a/Facepunch.Steamworks/Client/Leaderboard.cs +++ b/Facepunch.Steamworks/Client/Leaderboard.cs @@ -99,14 +99,66 @@ namespace Facepunch.Steamworks /// If onlyIfBeatsOldScore is true, the score will only be updated if it beats the existing score, else it will always /// be updated. /// - public void AddScore( bool onlyIfBeatsOldScore, int score, params int[] subscores ) + public bool AddScore( bool onlyIfBeatsOldScore, int score, params int[] subscores ) { - if ( !IsValid ) return; + if ( !IsValid ) return false; var flags = LeaderboardUploadScoreMethod.ForceUpdate; if ( onlyIfBeatsOldScore ) flags = LeaderboardUploadScoreMethod.KeepBest; client.native.userstats.UploadLeaderboardScore( BoardId, flags, score, subscores, subscores.Length ); + + return true; + } + + /// + /// Callback invoked by when score submission + /// is complete. + /// + /// If true, the score was submitted + /// If successful, information about the new entry + public delegate void AddScoreCallback( bool success, AddScoreResult result ); + + /// + /// Information about a newly submitted score. + /// + public struct AddScoreResult + { + public int Score; + public bool ScoreChanged; + public int GlobalRankNew; + public int GlobalRankPrevious; + } + + /// + /// Add a score to this leaderboard. + /// Subscores are totally optional, and can be used for other game defined data such as laps etc.. although + /// they have no bearing on sorting at all + /// If onlyIfBeatsOldScore is true, the score will only be updated if it beats the existing score, else it will always + /// be updated. + /// Information about the newly submitted score is passed to the optional . + /// + public bool AddScore( bool onlyIfBeatsOldScore, int score, int[] subscores = null, AddScoreCallback callback = null ) + { + if ( !IsValid ) return false; + + if ( subscores == null ) subscores = new int[0]; + + var flags = LeaderboardUploadScoreMethod.ForceUpdate; + if ( onlyIfBeatsOldScore ) flags = LeaderboardUploadScoreMethod.KeepBest; + + client.native.userstats.UploadLeaderboardScore( BoardId, flags, score, subscores, subscores.Length, callback != null ? (Action) (( result, error ) => + { + callback( !error && result.Success != 0, new AddScoreResult + { + Score = result.Score, + ScoreChanged = result.ScoreChanged != 0, + GlobalRankNew = result.GlobalRankNew, + GlobalRankPrevious = result.GlobalRankPrevious + } ); + }) : null ); + + return true; } /// @@ -145,6 +197,10 @@ namespace Facepunch.Steamworks [ThreadStatic] private static List _sEntryBuffer; + /// + /// Callback invoked by when + /// a query is complete. + /// public delegate void FetchScoresCallback( bool success, Entry[] results ); /// @@ -174,14 +230,12 @@ namespace Facepunch.Steamworks return true; } - private unsafe void OnScores( LeaderboardScoresDownloaded_t result, bool error ) + private void OnScores( LeaderboardScoresDownloaded_t result, bool error ) { IsQuerying = false; if ( client == null ) return; - - if ( error ) - return; + if ( error ) return; var list = new List(); ReadScores( result, list );