Sorting Leaderboard (via Steam) problem (LeastSquares Dev)

Hello, i want to make steam leaderboard with this package:

this is the only free viable package on unity store, but seems done with some errors in code (i have already fix few of them).

The sorting (SortType) doesn’t work anymore. Discord of the creator and mail are down, so i hope someone can help me here :slight_smile:

There is two main script to manage Leaderboard:

1# SteamLeaderboard:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Steamworks;
using Steamworks.Data;
using UnityEngine;
using UnityEngine.Serialization;

namespace LeastSquares
{
    /// <summary>
    /// Class that represents a Steam leaderboard.
    /// </summary>
    public class SteamLeaderboard : MonoBehaviour
    {
        public string Name;
        public SteamLeaderboardSort SortType = SteamLeaderboardSort.Descending;
        public SteamLeaderboardDisplay DisplayType = SteamLeaderboardDisplay.Numeric;
        private Leaderboard? _leaderboard;

        /// <summary>
        /// Creates or finds the leaderboard if it doesnt exist. Does not do anything if Steam has not been loaded first.
        /// </summary>
        private async Task CreateOrFindLeaderboard()
        {

            if (_leaderboard != null || !SteamClient.IsValid) return;
            _leaderboard = await SteamUserStats.FindOrCreateLeaderboardAsync(Name, (LeaderboardSort) SortType, (LeaderboardDisplay) DisplayType);

        }

        /// <summary>
        /// Submits a new score to the steam leaderboard. Only updates it if its better than the previous one
        /// </summary>
        /// <param name="newScore">The new score for the user</param>
        public async void SubmitScore(int newScore)
        { 
            await CreateOrFindLeaderboard();
            if (_leaderboard != null)
            {
                await _leaderboard.Value.SubmitScoreAsync(newScore);
                Debug.Log($"Sent score {newScore}");
            }
        }
        
        /// <summary>
        /// Replaces the user's score, even if its lower, with a new one
        /// </summary>
        /// <param name="newScore">The score to replace with</param>
        public async void ReplaceScore(int newScore)
        { 
            await CreateOrFindLeaderboard();
            if (_leaderboard != null)
            {
                await _leaderboard.Value.ReplaceScore(newScore);               
                Debug.Log($"Replace score {newScore}");
            }
        }

        /// <summary>
        /// Get scores from all users
        /// </summary>
        /// <returns>A list of leaderboard entries from all players</returns>
        public async Task<LeaderboardEntry[]> GetScores(int entriesToRetrieve, int offset = 1)
        { 
            await CreateOrFindLeaderboard();
            if (!_leaderboard.HasValue) return await Task.Run(() => new LeaderboardEntry[]{});
            return await _leaderboard.Value.GetScoresAsync(entriesToRetrieve, offset);
        }
        
        /// <summary>
        /// Get scores around the current steam user
        /// </summary>
        /// <returns>A list of leaderboard entries around the current steam user</returns>
        public async Task<LeaderboardEntry[]> GetScoresAroundUser(int entriesAround)
        { 
            await CreateOrFindLeaderboard();
            if (!_leaderboard.HasValue) return await Task.Run(() => new LeaderboardEntry[]{});
            return await _leaderboard.Value.GetScoresAroundUserAsync(-entriesAround, entriesAround);
        }
        
        /// <summary>
        /// Get scores from friends
        /// </summary>
        /// <returns>A list of leaderboard entries from you and your steam friends</returns>
        public async Task<LeaderboardEntry[]> GetScoresFromFriends()
        { 
            await CreateOrFindLeaderboard();
            if (!_leaderboard.HasValue) return await Task.Run(() => new LeaderboardEntry[]{});
            return await _leaderboard.Value.GetScoresFromFriendsAsync();
        }

        /// <summary>
        /// Gets the best score for the user
        /// </summary>
        /// <returns>An int representing the best score for the user</returns>
        public async Task<LeaderboardEntry?> GetBestScore()
        {
            var result = await GetScoresAroundUser(1);
            if (result is { Length: > 0 })
                return result[0];
            return null;
        }
    }

    /// <summary>
    /// Enum representing the sorting method of the leaderboard
    /// </summary>
    [Serializable]
    public enum SteamLeaderboardSort
    {

        [EnumMember]
        Descending = 2 ,

        [EnumMember]
        Ascending = 1,
    }

    /// <summary>
    /// Enum representing the display method of the leaderboard
    /// </summary>
    [Serializable]
    public enum SteamLeaderboardDisplay
    {
        [EnumMember]
        Numeric = 1,
        [EnumMember]
        TimeSeconds = 2,
        [EnumMember]
        TimeMilliseconds = 3,
    }
}

2# LeaderboardUI

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using LeastSquares;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

namespace LeastSquares
{
    /// <summary>
    /// Script to fill the leaderboard UI from the Steam leaderboard
    /// </summary>
    public class LeaderboardUI : MonoBehaviour
    {
        public int EntriesToShowAtOnce = 100;
        public GameObject EntryPrefab;
        public TMP_InputField Input;
        public SteamLeaderboard Leaderboard;
        public LeaderboardType Type = LeaderboardType.Global;
        private List<GameObject> _rows = new ();
        private int _offset;

        void Start()
        {
            RefreshScores();
        }

        /// <summary>
        /// Fill the leaderboardUI with new scores
        /// </summary>
        async void RefreshScores()
        {
            LeaderboardEntry[] scores;
            switch (Type)
            {
                case LeaderboardType.Global:
                    scores = await Leaderboard.GetScores(EntriesToShowAtOnce-1, 1 + _offset);
                    break;
                case LeaderboardType.Friends:
                    scores = await Leaderboard.GetScoresFromFriends();
                    break;
                case LeaderboardType.AroundUser:
                    scores = await Leaderboard.GetScoresAroundUser(EntriesToShowAtOnce / 2);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            RegenerateUI(scores);
        }

        /// <summary>
        /// Renegenerate the leaderboard rows
        /// </summary>
        /// <param name="scores">An array of leaderboard entries</param>
        async void RegenerateUI(LeaderboardEntry[] scores)
        {
            var oldRows = _rows;
            _rows = new List<GameObject>();
            for (var i = 0; i < scores.Length; i++)
            {
                var go = await CreateRow(scores[i]);

                _rows.Add(go);
            }

            for (var i = 0; i < oldRows.Count; i++)
            {
                Destroy(oldRows[i]);
            }
        }

        /// <summary>
        /// Create a row for the leaderboard entry
        /// </summary>
        /// <param name="entry">The given LeaderboardEntry</param>
        /// <returns>A GameObject representing the row</returns>
        private async Task<GameObject> CreateRow(LeaderboardEntry entry)
        {
            var go = Instantiate(EntryPrefab, transform);
            var row = go.GetComponent<LeaderboardUIRow>();
            row.Score.text = entry.Score.ToString();
            row.Name.text = entry.User.Name;
            row.Rank.text = entry.GlobalRank.ToString();
            var maybeImage = await entry.User.GetSmallAvatarAsync();
            if (maybeImage.HasValue)
            {
                var tex2D = maybeImage.Value.Convert();
                row.Avatar.sprite = Sprite.Create(tex2D, new Rect(0, 0, tex2D.width, tex2D.height), Vector2.zero);
            }

            return go;
        }

        /// <summary>
        /// Upload the score in the text field to the leaderboard. Called from the "Save Score" button
        /// </summary>
        public void SaveScore()
        {
            var text = Input.text;
            Leaderboard.ReplaceScore(int.Parse(text));

            RefreshScores();
            //SteamUserStats.ResetAll(true);

        }
        
    }

    [Serializable]
    public enum LeaderboardType
    {
        Global,
        Friends,
        AroundUser
    }
}

Descending && Time Seconds && TimeMiliseconds does’nt work

Is this because Leaderboard is from 480appID (test)?

In case there is Steamworks.Data.LeaderboardSort decompil:

#region assembly Facepunch.Steamworks.Win64, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// G:\2000\Assets\LeaderboardForSteam\Plugins\Facepunch.Steamworks.Win64.dll
// Decompiled with ICSharpCode.Decompiler 8.1.1.7464
#endregion

namespace Steamworks.Data;

public enum LeaderboardSort
{
    //
    // Résumé :
    //     The top-score is the lowest number
    Ascending = 1,
    //
    // Résumé :
    //     The top-score is the highest number
    Descending
}

Thanks for help