using Steamworks; using UnityEngine; using UnityEngine.Events; namespace HeathenEngineering.SteamApi.PlayerServices { [CreateAssetMenu(menuName = "Steamworks/Player Services/Leaderboard Data")] public class SteamworksLeaderboardData : ScriptableObject { public bool createIfMissing; public ELeaderboardSortMethod sortMethod; public ELeaderboardDisplayType displayType; public string leaderboardName; public int MaxDetailEntries; [HideInInspector] public SteamLeaderboard_t? LeaderboardId; [HideInInspector] public LeaderboardEntry_t? UserEntry; public UnityEvent BoardFound = new UnityEvent(); public LeaderboardScoresDownloadedEvent OnQueryResults = new LeaderboardScoresDownloadedEvent(); public UnityLeaderboardRankUpdateEvent UserRankLoaded = new UnityLeaderboardRankUpdateEvent(); public UnityLeaderboardRankChangeEvent UserRankChanged = new UnityLeaderboardRankChangeEvent(); public UnityLeaderboardRankChangeEvent UserNewHighRank = new UnityLeaderboardRankChangeEvent(); private CallResult OnLeaderboardFindResultCallResult; private CallResult OnLeaderboardScoresDownloadedCallResult; private CallResult OnLeaderboardScoreUploadedCallResult; public void Register() { OnLeaderboardFindResultCallResult = CallResult.Create(OnLeaderboardFindResult); OnLeaderboardScoresDownloadedCallResult = CallResult.Create(OnLeaderboardScoresDownloaded); OnLeaderboardScoreUploadedCallResult = CallResult.Create(OnLeaderboardScoreUploaded); if (createIfMissing) { FindOrCreateLeaderboard(sortMethod, displayType); } else { FindLeaderboard(); } } private void FindOrCreateLeaderboard(ELeaderboardSortMethod sortMethod, ELeaderboardDisplayType displayType) { SteamAPICall_t hAPICall = SteamUserStats.FindOrCreateLeaderboard(leaderboardName, sortMethod, displayType); OnLeaderboardFindResultCallResult.Set(hAPICall); } private void FindLeaderboard() { SteamAPICall_t hAPICall = SteamUserStats.FindLeaderboard(leaderboardName); OnLeaderboardFindResultCallResult.Set(hAPICall); } public void RefreshUserEntry() { if (!LeaderboardId.HasValue) { Debug.LogError(base.name + " Leaderboard Data Object, cannot download scores, the leaderboard has not been initalized and cannot download scores."); return; } CSteamID[] prgUsers = new CSteamID[1] { SteamUser.GetSteamID() }; SteamAPICall_t hAPICall = SteamUserStats.DownloadLeaderboardEntriesForUsers(LeaderboardId.Value, prgUsers, 1); OnLeaderboardScoresDownloadedCallResult.Set(hAPICall, OnLeaderboardUserRefreshRequest); } public void UploadScore(int score, ELeaderboardUploadScoreMethod method) { if (!LeaderboardId.HasValue) { Debug.LogError(base.name + " Leaderboard Data Object, cannot upload scores, the leaderboard has not been initalized and cannot upload scores."); return; } SteamAPICall_t hAPICall = SteamUserStats.UploadLeaderboardScore(LeaderboardId.Value, method, score, null, 0); OnLeaderboardScoreUploadedCallResult.Set(hAPICall); } public void UploadScore(int score, int[] scoreDetails, ELeaderboardUploadScoreMethod method) { if (!LeaderboardId.HasValue) { Debug.LogError(base.name + " Leaderboard Data Object, cannot upload scores, the leaderboard has not been initalized and cannot upload scores."); return; } SteamAPICall_t hAPICall = SteamUserStats.UploadLeaderboardScore(LeaderboardId.Value, method, score, scoreDetails, scoreDetails.Length); OnLeaderboardScoreUploadedCallResult.Set(hAPICall); } public void QueryTopEntries(int count) { QueryEntries(ELeaderboardDataRequest.k_ELeaderboardDataRequestGlobal, 0, count); } public void QueryFriendEntries(int aroundPlayer) { QueryEntries(ELeaderboardDataRequest.k_ELeaderboardDataRequestFriends, -aroundPlayer, aroundPlayer); } public void QueryPeerEntries(int aroundPlayer) { QueryEntries(ELeaderboardDataRequest.k_ELeaderboardDataRequestGlobalAroundUser, -aroundPlayer, aroundPlayer); } public void QueryEntries(ELeaderboardDataRequest requestType, int rangeStart, int rangeEnd) { if (!LeaderboardId.HasValue) { Debug.LogError(base.name + " Leaderboard Data Object, cannot download scores, the leaderboard has not been initalized and cannot download scores."); return; } SteamAPICall_t hAPICall = SteamUserStats.DownloadLeaderboardEntries(LeaderboardId.Value, requestType, rangeStart, rangeEnd); OnLeaderboardScoresDownloadedCallResult.Set(hAPICall, OnLeaderboardScoresDownloaded); } private void OnLeaderboardScoreUploaded(LeaderboardScoreUploaded_t param, bool bIOFailure) { if (param.m_bSuccess == 0 || bIOFailure) { Debug.LogError(base.name + " Leaderboard Data Object, failed to upload score to Steam: Success code = " + param.m_bSuccess, this); } RefreshUserEntry(); } private void OnLeaderboardUserRefreshRequest(LeaderboardScoresDownloaded_t param, bool bIOFailure) { ProcessScoresDownloaded(param, bIOFailure); } private void OnLeaderboardScoresDownloaded(LeaderboardScoresDownloaded_t param, bool bIOFailure) { bool playerIncluded = ProcessScoresDownloaded(param, bIOFailure); OnQueryResults.Invoke(new LeaderboardScoresDownloaded { bIOFailure = bIOFailure, scoreData = param, playerIncluded = playerIncluded }); } private bool ProcessScoresDownloaded(LeaderboardScoresDownloaded_t param, bool bIOFailure) { bool result = false; if (!bIOFailure) { CSteamID steamID = SteamUser.GetSteamID(); for (int i = 0; i < param.m_cEntryCount; i++) { int[] array = null; LeaderboardEntry_t pLeaderboardEntry; if (MaxDetailEntries < 1) { SteamUserStats.GetDownloadedLeaderboardEntry(param.m_hSteamLeaderboardEntries, i, out pLeaderboardEntry, array, MaxDetailEntries); } else { array = new int[MaxDetailEntries]; SteamUserStats.GetDownloadedLeaderboardEntry(param.m_hSteamLeaderboardEntries, i, out pLeaderboardEntry, array, MaxDetailEntries); } if (pLeaderboardEntry.m_steamIDUser.m_SteamID != steamID.m_SteamID) { continue; } result = true; if (!UserEntry.HasValue || UserEntry.Value.m_nGlobalRank != pLeaderboardEntry.m_nGlobalRank) { LeaderboardUserData arg = new LeaderboardUserData { leaderboardName = leaderboardName, leaderboardId = LeaderboardId.Value, entry = pLeaderboardEntry, details = array }; LeaderboardRankChangeData arg2 = new LeaderboardRankChangeData { leaderboardName = leaderboardName, leaderboardId = LeaderboardId.Value, newEntry = pLeaderboardEntry, oldEntry = (UserEntry.HasValue ? new LeaderboardEntry_t?(UserEntry.Value) : ((LeaderboardEntry_t?)null)) }; UserEntry = pLeaderboardEntry; UserRankLoaded.Invoke(arg); UserRankChanged.Invoke(arg2); if (arg2.newEntry.m_nGlobalRank < (arg2.oldEntry.HasValue ? arg2.oldEntry.Value.m_nGlobalRank : int.MaxValue)) { UserNewHighRank.Invoke(arg2); } } else { LeaderboardUserData arg3 = new LeaderboardUserData { leaderboardName = leaderboardName, leaderboardId = LeaderboardId.Value, entry = pLeaderboardEntry, details = array }; UserEntry = pLeaderboardEntry; UserRankLoaded.Invoke(arg3); } } } return result; } private void OnLeaderboardFindResult(LeaderboardFindResult_t param, bool bIOFailure) { if (param.m_bLeaderboardFound == 0 || bIOFailure) { Debug.LogError("Failed to find leaderboard", this); } else if (param.m_bLeaderboardFound != 0) { LeaderboardId = param.m_hSteamLeaderboard; BoardFound.Invoke(); RefreshUserEntry(); } } } }