/** * Copyright 2019 The Knights Of Unity, created by Pawel Stolarczyk * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using DemoGame.Scripts.Clans; using DemoGame.Scripts.Friends; using DemoGame.Scripts.Menus; using DemoGame.Scripts.Profile; using DemoGame.Scripts.Session; using Nakama; using UnityEngine; using UnityEngine.UI; namespace DemoGame.Scripts.Leaderboards { /// /// Manages leaderboards UI. /// public class LeaderboardPanel : Menu { #region Fields /// /// Parent for all leaderboards records. /// [SerializeField] private RectTransform _userList = null; /// /// Prefab of a single leaderboard record. /// [SerializeField] private LeaderboardEntry _leaderboardEntryPrefab = null; /// /// Maximum number of records displayed on a single page. /// [SerializeField] private int _recordsPerPage = 100; #region Buttons /// /// Shows global leaderboard. /// [SerializeField] private Button _showGlobal = null; /// /// Shows clan leaderboards. /// [SerializeField] private Button _showClan = null; /// /// Shows friends leaderboards. /// [SerializeField] private Button _showFriends = null; /// /// Shows next page of leaderboard results. /// [SerializeField] private Button _nextPageButton = null; /// /// Shows previous page of leaderboard results. /// [SerializeField] private Button _prevPageButton = null; #endregion /// /// Invoked upon clicking . /// private Action _nextPage; /// /// Invoked upon clicking . /// private Action _prevPage; #endregion #region Properties /// /// Returns from for easier access. /// private Client Client { get { return NakamaSessionManager.Instance.Client; } } /// /// Returns from for easier access. /// private ISession Session { get { return NakamaSessionManager.Instance.Session; } } #endregion #region Mono /// /// Calls method upon connecting to Nakama. /// private void Awake() { base.SetBackButtonHandler(MenuManager.Instance.HideTopMenu); if (NakamaSessionManager.Instance.IsConnected == false) { NakamaSessionManager.Instance.OnConnectionSuccess += Init; } else { Init(); } } #endregion #region Methods /// /// Adds handlers to buttons. /// private void Init() { NakamaSessionManager.Instance.OnConnectionSuccess -= Init; _showClan.onClick.AddListener(() => ShowClanLeaderboards(null)); _showGlobal.onClick.AddListener(() => ShowGlobalLeaderboards(null)); _showFriends.onClick.AddListener(() => ShowFriendsLeaderboards(null)); ShowGlobalLeaderboards(); } #region RecordListFilling /// /// Fills with user records sorted by the score. /// public async void ShowGlobalLeaderboards(string cursor = null) { IApiLeaderboardRecordList records = await LeaderboardManager.GetGlobalLeaderboarsAsync(Client, Session, _recordsPerPage, cursor); if (records != null) { SetLeaderboardsCursor(records, ShowGlobalLeaderboards); FillLeaderboard(records.Records); _showFriends.interactable = true; _showClan.interactable = true; _showGlobal.interactable = false; } } /// /// Fills with records of all members of the clan local user belongs to. /// public async void ShowClanLeaderboards(string cursor) { IUserGroupListUserGroup clan = await ClanManager.GetUserClanAsync(Client, Session); if (clan == null) { return; } IApiLeaderboardRecordList records = await LeaderboardManager.GetClanLeaderboarsAsync(Client, Session, clan.Group, _recordsPerPage, cursor); if (records != null) { SetLeaderboardsCursor(records, ShowClanLeaderboards); FillLeaderboard(records.OwnerRecords); _showFriends.interactable = true; _showClan.interactable = false; _showGlobal.interactable = true; } } /// /// Gets ids of all friends of local user and displays their records. /// This also includes local user. /// public async void ShowFriendsLeaderboards(string cursor) { IApiFriends friends = await FriendsManager.LoadFriendsAsync(Client, Session); if (friends == null) { return; } IApiLeaderboardRecordList records = await LeaderboardManager.GetFriendsLeaderboarsAsync(Client, Session, friends.Friends, _recordsPerPage, cursor); if (records != null) { SetLeaderboardsCursor(records, ShowFriendsLeaderboards); FillLeaderboard(records.OwnerRecords); _showFriends.interactable = false; _showClan.interactable = true; _showGlobal.interactable = true; } } #endregion /// /// Sets and onClick events. /// If there is no next or previous page, disables interactions with these buttons. /// /// /// Contains and /// responsible for iterating through pages. /// /// /// Method used to receive . This method will be called to iterate /// through pages using cursors. /// private void SetLeaderboardsCursor(IApiLeaderboardRecordList records, Action caller) { if (records.PrevCursor != null) { _prevPageButton.interactable = true; _prevPageButton.onClick.RemoveAllListeners(); _prevPageButton.onClick.AddListener(() => caller(records.PrevCursor)); } else { _prevPageButton.interactable = false; } if (records.NextCursor != null) { _nextPageButton.interactable = true; _nextPageButton.onClick.RemoveAllListeners(); _nextPageButton.onClick.AddListener(() => caller(records.NextCursor)); } else { _nextPageButton.interactable = false; } } /// /// Destroys every child of , then /// creates an instance of for each record. /// private void FillLeaderboard(IEnumerable recordList) { foreach (Transform entry in _userList) { Destroy(entry.gameObject); } int rank = 1; string localId = NakamaSessionManager.Instance.Account.User.Id; foreach (IApiLeaderboardRecord record in recordList) { LeaderboardEntry entry = Instantiate(_leaderboardEntryPrefab, _userList); string username = record.Username; if (localId == record.OwnerId) { username += " (You)"; } entry.SetPlayer(username, rank, record.Score, () => OnProfileClicked(record.OwnerId)); rank += 1; } } /// /// Invoked whenever user clicks button of a record. /// private async void OnProfileClicked(string userId) { IApiUser user = await NakamaSessionManager.Instance.GetUserInfoAsync(userId, null); if (user != null) { ProfilePopup.Instance.Show(userId); } } /// /// Checks whether local user is a member of a clan, then disables or enables /// button accordingly. Shows this menu. /// public async override void Show() { Client client = NakamaSessionManager.Instance.Client; ISession session = NakamaSessionManager.Instance.Session; // If local user is not a member of a clan, disable clan leaderboards IUserGroupListUserGroup clan = await ClanManager.GetUserClanAsync(client, session); if (clan != null) { _showClan.gameObject.SetActive(true); } else { // User is not a member of any clan // Hiding clan score tab if (_showClan.interactable == true) { // Last showed tab is clan tab // Switching to other tab ShowGlobalLeaderboards(); } _showClan.gameObject.SetActive(false); } base.Show(); } #endregion } }