rlabrecque/Steamworks.NET

[Leaderboards] SteamUserStats.GetDownloadedLeaderboardEntry() Errors

Closed this issue · 3 comments

I'm getting memory crashes when reading leaderboard entries via SteamUserStats.GetDownloadedLeaderboardEntry(). The full line with params I'm using is:

SteamUserStats.GetDownloadedLeaderboardEntry(leaderboardDownloadResult.m_hSteamLeaderboardEntries, i, out var userEntry, new int[] { }, 64);

If I uncomment this single line, the builds work flawlessly - both PC and Steam Deck.

As one of the out parameters is the userEntry of index i, I've tried caching LeadboardScoresDownloaded_t along with storing it to a new object so there are no references for when it's garbage collected, but neither method works. It interferes with other memory addresses when reading the call stack. The crashes are 100% reproducible, but the call stacks vary every time due to memory management corruption.

The surrounding context on how I'm using the callback and result is:

var downloadLeaderboardCallResult = CallResult<LeaderboardScoresDownloaded_t>.Create();
downloadLeaderboardCallResult.Set(downloadLeaderboardCall, (leaderboardDownloadResult, failure) =>
{
    if (!failure)
    {
        CurrentLeaderboardEntries.Clear();
        
        for (int i = 0; i < leaderboardDownloadResult.m_cEntryCount; i++)
        {
            SteamUserStats.GetDownloadedLeaderboardEntry(leaderboardDownloadResult.m_hSteamLeaderboardEntries, i, out var userEntry, new int[] { }, 64);
                        
            var newEntry = new LeaderboardEntry
            {
                Rank = userEntry.m_nGlobalRank,
                UserID = userEntry.m_steamIDUser,
                Score = userEntry.m_nScore
            };

            if (GetPlayerNameFromUserID(userEntry.m_steamIDUser).Equals(GetPlayerNameFromUserID(SteamUser.GetSteamID())))
            {
                CurrentPlayerEntry = newEntry;
                CurrentPlayerFriendsRank = i + 1;
                DidFindCurrentPlayer = true;
            }
                        
            CurrentLeaderboardEntries.Add(newEntry);
        }

        didDownloadEntries = true;
    }
    else
    {
        error = true;
    }
});

SteamUserStats.FindOrCreateLeaderboard() works as expected.

I've tried upgrading the Unity version, with no fix.
I've tried switching from IL2CPP to Mono builds with no fix.

Any help would be greatly appreciated, as without reading the leaderboard entries this is a blocker on having the leaderboard feature.

Can you provide value of Packsize.value on all your target platforms? are they correct?

namespace Steamworks {
public static class Packsize {
#if VALVE_CALLBACK_PACK_LARGE
public const int value = 8;
#elif VALVE_CALLBACK_PACK_SMALL
public const int value = 4;
#endif

Hi, thanks for replying back. I removed this wrapper from the project yesterday and I'm not sure where that pack size parameter is configured. The callback only had 13 entries on the leaderboard if that helps?

Nevermind, I just reproduced it, check the last part of this in Steamworks' Documentation:

SteamUserStats.GetDownloadedLeaderboardEntry(leaderboardDownloadResult.m_hSteamLeaderboardEntries, i, out var userEntry, new int[] { }, 64);

you're not passing any details, use 0;