using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace UnityEngine.SocialPlatforms.GameCenter { #if ENABLE_GAMECENTER using UnityEngine.SocialPlatforms.Impl; [StructLayout (LayoutKind.Sequential)] internal struct GcUserProfileData { public string userName; public string userID; public int isFriend; public Texture2D image; public UserProfile ToUserProfile() { return new UserProfile(userName, userID, (isFriend==1?true:false), UserState.Offline, image); } public void AddToArray(ref UserProfile[] array, int number) { if (array.Length > number && number >= 0) array[number] = ToUserProfile(); else Debug.Log("Index number out of bounds when setting user data"); } } [StructLayout (LayoutKind.Sequential)] internal struct GcAchievementDescriptionData { public string m_Identifier; public string m_Title; public Texture2D m_Image; public string m_AchievedDescription; public string m_UnachievedDescription; public int m_Hidden; public int m_Points; public AchievementDescription ToAchievementDescription() { return new AchievementDescription( m_Identifier, m_Title, m_Image, m_AchievedDescription, m_UnachievedDescription, m_Hidden == 0 ? false : true, m_Points); } } [StructLayout (LayoutKind.Sequential)] internal struct GcAchievementData { public string m_Identifier; public double m_PercentCompleted; public int m_Completed; public int m_Hidden; public int m_LastReportedDate; public Achievement ToAchievement() { return new Achievement( m_Identifier, m_PercentCompleted, m_Completed == 0 ? false : true, m_Hidden == 0 ? false : true, new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(m_LastReportedDate)); } } [StructLayout (LayoutKind.Sequential)] internal struct GcScoreData { public string m_Category; public int m_ValueLow; public int m_ValueHigh; public int m_Date; public string m_FormattedValue; public string m_PlayerID; public int m_Rank; public Score ToScore() { return new Score( m_Category, (((Int64)m_ValueHigh) << 32) + m_ValueLow, m_PlayerID, new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(m_Date), m_FormattedValue, m_Rank); } } public partial class GameCenterPlatform : ISocialPlatform { static Action s_AuthenticateCallback; static Action s_FriendsCallback; static Action s_AchievementDescriptionLoaderCallback; static Action s_AchievementLoaderCallback; static Action s_ProgressCallback; static Action s_ScoreCallback; static Action s_ScoreLoaderCallback; static Action s_LeaderboardCallback; static Action s_UsersCallback; static AchievementDescription[] s_adCache = new AchievementDescription[0]; static UserProfile[] s_friends = new UserProfile[0]; static UserProfile[] s_users = new UserProfile[0]; static Action s_ResetAchievements; private static LocalUser m_LocalUser; private static List m_GcBoards = new List(); static void ClearAchievementDescriptions(int size) { if (s_adCache == null || s_adCache.Length != size) s_adCache = new AchievementDescription[size]; } static void SetAchievementDescription(GcAchievementDescriptionData data, int number) { s_adCache[number] = data.ToAchievementDescription(); } static void SetAchievementDescriptionImage(Texture2D texture, int number) { if (s_adCache.Length <= number || number < 0) { Debug.Log("Achievement description number out of bounds when setting image"); return; } s_adCache[number].SetImage(texture); } static void TriggerAchievementDescriptionCallback() { if (s_AchievementDescriptionLoaderCallback != null && s_adCache != null) { if (s_adCache.Length == 0) Debug.Log("No achivevement descriptions returned"); s_AchievementDescriptionLoaderCallback(s_adCache); } } static void AuthenticateCallbackWrapper(int result) { if (s_AuthenticateCallback != null) { PopulateLocalUser(); s_AuthenticateCallback((result == 1 ? true : false)); } } static void ClearFriends(int size) { SafeClearArray(ref s_friends, size); } static void SetFriends(GcUserProfileData data, int number) { data.AddToArray(ref s_friends, number); } static void SetFriendImage(Texture2D texture, int number) { SafeSetUserImage(ref s_friends, texture, number); } static void TriggerFriendsCallbackWrapper(int result) { if (s_friends != null) m_LocalUser.SetFriends(s_friends); if (s_FriendsCallback != null) s_FriendsCallback((result == 1 ? true : false)); } static void AchievementCallbackWrapper(GcAchievementData[] result) { if (s_AchievementLoaderCallback != null) { if (result.Length == 0) Debug.Log("No achivevements returned"); Achievement[] migrated = new Achievement[result.Length]; for (int i = 0; i < result.Length; ++i) migrated[i] = result[i].ToAchievement(); s_AchievementLoaderCallback(migrated); } } static void ProgressCallbackWrapper(bool success) { if (s_ProgressCallback != null) s_ProgressCallback(success); } static void ScoreCallbackWrapper(bool success) { if (s_ScoreCallback != null) s_ScoreCallback(success); } static void ScoreLoaderCallbackWrapper(GcScoreData[] result) { if (s_ScoreLoaderCallback != null) { Score[] migrated = new Score[result.Length]; for (int i = 0; i < result.Length; ++i) migrated[i] = result[i].ToScore(); s_ScoreLoaderCallback(migrated); } } void ISocialPlatform.LoadFriends(ILocalUser user, Action callback) { s_FriendsCallback = callback; Internal_LoadFriends(); } void ISocialPlatform.Authenticate(ILocalUser user, Action callback) { s_AuthenticateCallback = callback; Internal_Authenticate(); } public ILocalUser localUser { get { if (m_LocalUser == null) m_LocalUser = new LocalUser(); if (Internal_Authenticated() && m_LocalUser.id == "0") PopulateLocalUser(); return m_LocalUser; } } private static void PopulateLocalUser() { m_LocalUser.SetAuthenticated(Internal_Authenticated()); m_LocalUser.SetUserName(Internal_UserName()); m_LocalUser.SetUserID(Internal_UserID()); m_LocalUser.SetUnderage(Internal_Underage()); m_LocalUser.SetImage(Internal_UserImage()); } public void LoadAchievementDescriptions(Action callback) { if (!VerifyAuthentication()) { callback(new AchievementDescription[0]); return; } s_AchievementDescriptionLoaderCallback = callback; Internal_LoadAchievementDescriptions(); } // TODO: This doesn't really work with the static callback wrapper, multiple progresses // could be reported at the same time. public void ReportProgress(string id, double progress, Action callback) { if (!VerifyAuthentication()) { callback(false); return; } s_ProgressCallback = callback; Internal_ReportProgress(id, progress); } public void LoadAchievements(Action callback) { if (!VerifyAuthentication()) { callback(new Achievement[0]); return; } s_AchievementLoaderCallback = callback; Internal_LoadAchievements(); } public void ReportScore(Int64 score, string board, Action callback) { if (!VerifyAuthentication()) { callback(false); return; } s_ScoreCallback = callback; Internal_ReportScore(score, board); } public void LoadScores(string category, Action callback) { if (!VerifyAuthentication()) { callback(new Score[0]); return; } s_ScoreLoaderCallback = callback; Internal_LoadScores(category); } public void LoadScores(ILeaderboard board, Action callback) { if (!VerifyAuthentication()) { callback(false); return; } s_LeaderboardCallback = callback; Leaderboard genericBoard = (Leaderboard)board; GcLeaderboard gcBoard = new GcLeaderboard(genericBoard); m_GcBoards.Add(gcBoard); if (genericBoard.GetUserFilter().Length > 0) gcBoard.Internal_LoadScoresWithUsers(board.id, (int)board.timeScope, genericBoard.GetUserFilter()); else gcBoard.Internal_LoadScores(board.id, board.range.from, board.range.count, (int)board.userScope, (int)board.timeScope); } static void LeaderboardCallbackWrapper(bool success) { if (s_LeaderboardCallback != null) s_LeaderboardCallback(success); } public bool GetLoading(ILeaderboard board) { if (!VerifyAuthentication()) return false; foreach (GcLeaderboard gcBoard in m_GcBoards) if (gcBoard.Contains((Leaderboard)board)) return gcBoard.Loading(); return false; } private bool VerifyAuthentication() { if (!localUser.authenticated) { Debug.Log ("Must authenticate first"); return false; } return true; } public void ShowAchievementsUI() { Internal_ShowAchievementsUI(); } public void ShowLeaderboardUI() { Internal_ShowLeaderboardUI(); } static void ClearUsers(int size) { SafeClearArray(ref s_users, size); } static void SetUser(GcUserProfileData data, int number) { data.AddToArray(ref s_users, number); } static void SetUserImage(Texture2D texture, int number) { SafeSetUserImage(ref s_users, texture, number); } static void TriggerUsersCallbackWrapper() { if (s_UsersCallback != null) s_UsersCallback(s_users); } public void LoadUsers(string[] userIds, Action callback) { if (!VerifyAuthentication()) { callback(new UserProfile[0]); return; } s_UsersCallback = callback; Internal_LoadUsers(userIds); } private static void SafeSetUserImage(ref UserProfile[] array, Texture2D texture, int number) { if (array.Length <= number || number < 0) { Debug.Log("Invalid texture when setting user image"); texture = new Texture2D(76, 76); } if (array.Length > number && number >= 0) array[number].SetImage(texture); else Debug.Log("User number out of bounds when setting image"); } private static void SafeClearArray(ref UserProfile[] array, int size) { if (array == null || array.Length != size) array = new UserProfile[size]; } public ILeaderboard CreateLeaderboard() { Leaderboard lb = new Leaderboard(); return (ILeaderboard)lb; } public IAchievement CreateAchievement() { Achievement achoo = new Achievement(); return (IAchievement)achoo; } static void TriggerResetAchievementCallback(bool result) { if (s_ResetAchievements != null) s_ResetAchievements(result); } } #else public class GameCenterPlatform : UnityEngine.SocialPlatforms.Local { static public void ResetAllAchievements(Action callback) { Debug.Log ("ResetAllAchievements - no effect in editor"); callback(true); } static public void ShowDefaultAchievementCompletionBanner(bool value) { Debug.Log ("ShowDefaultAchievementCompletionBanner - no effect in editor"); } static public void ShowLeaderboardUI(string leaderboardID, TimeScope timeScope) { Debug.Log ("ShowLeaderboardUI - no effect in editor"); } } #endif }