// called on game thread
        public void CreateWithInvitationScreen(int minOpponents, int maxOpponents,
                                               int variant, Action <bool, TurnBasedMatch> callback)
        {
            Logger.d(string.Format("AndroidTbmpClient.CreateWithInvitationScreen, " +
                                   "opponents {0}-{1}, variant {2}", minOpponents, maxOpponents,
                                   variant));

            mClient.CallClientApi("tbmp launch invitation screen", () => {
                AndroidJavaClass klass = JavaUtil.GetClass(
                    JavaConsts.SupportSelectOpponentsHelperActivity);
                klass.CallStatic("launch", false, mClient.GetActivity(),
                                 new SelectOpponentsProxy(this, callback, variant),
                                 Logger.DebugLogEnabled,
                                 minOpponents, maxOpponents);
            }, (bool success) => {
                if (!success)
                {
                    Logger.w("Failed to create tbmp w/ invite screen: client disconnected.");
                    if (callback != null)
                    {
                        callback.Invoke(false, null);
                    }
                }
            });
        }
Example #2
0
        /// <summary>
        /// Used internally when switching user.
        /// </summary>
        /// <param name="onDataLoaded">Action to invoke when data has been loaded.</param>
        public static void LoadDataString(UnityAction <string> onDataLoaded)
        {
#if CLOUDONCE_DEBUG
            Logger.d("Switching user. Loading default save game.");
#endif
            PlayGamesPlatform.Instance.SavedGame.OpenWithAutomaticConflictResolution(
                saveGameFileName,
                DataSource.ReadCacheOrNetwork,
                ConflictResolutionStrategy.UseLongestPlaytime,
                (status, metadata) =>
            {
                if (status == SavedGameRequestStatus.Success)
                {
                    PlayGamesPlatform.Instance.SavedGame.ReadBinaryData(
                        metadata,
                        (requestStatus, bytes) =>
                    {
                        if (requestStatus == SavedGameRequestStatus.Success)
                        {
                            s_timeWhenCloudSaveWasLoaded = Time.realtimeSinceStartup;
                            var dataString = GetDataString(bytes);
                            onDataLoaded.Invoke(dataString);
                        }
                        else
                        {
                            onDataLoaded.Invoke(null);
                        }
                    });
                }
                else
                {
                    onDataLoaded.Invoke(null);
                }
            });
        }
Example #3
0
        // called from game thread
        public void UnlockAchievement(string achId, Action <bool> callback)
        {
            // if the local cache says it's unlocked, we don't have to do anything
            Logger.d("AndroidClient.UnlockAchievement: " + achId);
            Achievement a = GetAchievement(achId);

            if (a != null && a.IsUnlocked)
            {
                Logger.d("...was already unlocked, so no-op.");
                if (callback != null)
                {
                    callback.Invoke(true);
                }
                return;
            }

            CallClientApi("unlock ach " + achId, () => {
                mGHManager.CallGmsApi("games.Games", "Achievements", "unlock", achId);
            }, callback);

            // update local cache
            a = GetAchievement(achId);
            if (a != null)
            {
                a.IsUnlocked = a.IsRevealed = true;
            }
        }
Example #4
0
        private void OnAuthenticated()
        {
            GooglePlayGames.OurUtils.PlayGamesHelperObject.RunOnGameThread(
                () =>
            {
                cloudOnceEvents.RaiseOnSignedInChanged(true);
                Logger.d("Successfully signed in to Google Play Game Services. Player: " + PlayerDisplayName);
                IsGuestUserDefault = false;
                GetPlayerImage();
                if (playerIdCache != null && !string.Equals(playerIdCache, PlayerID, StringComparison.InvariantCulture))
                {
                    // Switching user
                    foreach (var achievement in Achievements.All)
                    {
                        achievement.ResetLocalState();
                    }

                    if (cloudSaveEnabled)
                    {
                        GooglePlayGamesCloudSaveWrapper.LoadDataString(OnDataStringLoaded);
                    }
                }
                else if (autoLoadEnabled && cloudSaveEnabled)
                {
                    Cloud.Storage.Load();
                }

                playerIdCache = PlayerID;
                if (Achievements.All.Length > 0)
                {
                    PlayGamesPlatform.Instance.LoadAchievements(UpdateAchievementsData);
                }
            });
        }
        // called on game thread
        public void CreateQuickMatch(int minOpponents, int maxOpponents, int variant,
                                     Action <bool, TurnBasedMatch> callback)
        {
            Logger.d(string.Format("AndroidTbmpClient.CreateQuickMatch, opponents {0}-{1}, var {2}",
                                   minOpponents, maxOpponents, variant));

            mClient.CallClientApi("tbmp create quick game", () => {
                ResultProxy proxy = new ResultProxy(this, "createMatch");
                proxy.SetMatchCallback(callback);
                AndroidJavaClass tbmpUtil = JavaUtil.GetClass(JavaConsts.SupportTbmpUtilsClass);
                using (AndroidJavaObject pendingResult = tbmpUtil.CallStatic <AndroidJavaObject>(
                           "createQuickMatch", mClient.GHManager.GetApiClient(),
                           minOpponents, maxOpponents, variant)) {
                    pendingResult.Call("setResultCallback", proxy);
                }
            }, (bool success) => {
                if (!success)
                {
                    Logger.w("Failed to create tbmp quick match: client disconnected.");
                    if (callback != null)
                    {
                        callback.Invoke(false, null);
                    }
                }
            });
        }
Example #6
0
        // called from game thread
        public void RevealAchievement(string achId, Action <bool> callback)
        {
            Logger.d("AndroidClient.RevealAchievement: " + achId);
            Achievement a = GetAchievement(achId);

            if (a != null && a.IsRevealed)
            {
                Logger.d("...was already revealed, so no-op.");
                if (callback != null)
                {
                    callback.Invoke(true);
                }
                return;
            }

            CallClientApi("reveal ach " + achId, () => {
                mGHManager.CallGmsApi("games.Games", "Achievements", "reveal", achId);
            }, callback);

            // update local cache
            a = GetAchievement(achId);
            if (a != null)
            {
                a.IsRevealed = true;
            }
        }
Example #7
0
        // called from game thread
        public void RegisterInvitationDelegate(InvitationReceivedDelegate deleg)
        {
            Logger.d("AndroidClient.RegisterInvitationDelegate");
            if (deleg == null)
            {
                Logger.w("AndroidClient.RegisterInvitationDelegate called w/ null argument.");
                return;
            }
            mInvitationDelegate = deleg;

            // install invitation listener, if we don't have one yet
            if (!mRegisteredInvitationListener)
            {
                Logger.d("Registering an invitation listener.");
                RegisterInvitationListener();
            }

            if (mInvitationFromNotification != null)
            {
                Logger.d("Delivering pending invitation from notification now.");
                Invitation inv = mInvitationFromNotification;
                mInvitationFromNotification = null;
                PlayGamesHelperObject.RunOnGameThread(() => {
                    if (mInvitationDelegate != null)
                    {
                        mInvitationDelegate.Invoke(inv, true);
                    }
                });
            }
        }
Example #8
0
        private Invitation ConvertInvitation(AndroidJavaObject invObj)
        {
            Logger.d("Converting Android invitation to our Invitation object.");
            string      invitationId = invObj.Call <string>("getInvitationId");
            int         invType      = invObj.Call <int>("getInvitationType");
            Participant inviter;

            using (AndroidJavaObject inviterObj = invObj.Call <AndroidJavaObject>("getInviter")) {
                inviter = JavaUtil.ConvertParticipant(inviterObj);
            }
            int variant = invObj.Call <int>("getVariant");

            Invitation.InvType type;

            switch (invType)
            {
            case JavaConsts.INVITATION_TYPE_REAL_TIME:
                type = Invitation.InvType.RealTime;
                break;

            case JavaConsts.INVITATION_TYPE_TURN_BASED:
                type = Invitation.InvType.TurnBased;
                break;

            default:
                Logger.e("Unknown invitation type " + invType);
                type = Invitation.InvType.Unknown;
                break;
            }

            Invitation result = new Invitation(type, invitationId, inviter, variant);

            Logger.d("Converted invitation: " + result.ToString());
            return(result);
        }
Example #9
0
        /// <summary>
        /// Initializes Google Play Game Services.
        /// </summary>
        /// <param name="activateCloudSave">Whether or not Cloud Saving should be activated.</param>
        /// <param name="autoSignIn">
        /// Whether or not <see cref="SignIn"/> will be called automatically once Google Play Game Services is initialized.
        /// </param>
        /// <param name="autoCloudLoad">
        /// Whether or not cloud data should be loaded automatically if the user is successfully signed in.
        /// Ignored if Cloud Saving is deactivated or the user fails to sign in.
        /// </param>
        public override void Initialize(bool activateCloudSave = true, bool autoSignIn = true, bool autoCloudLoad = true)
        {
            if (initializing)
            {
                return;
            }
#if CLOUDONCE_DEBUG
            Debug.Log("Initializing Google Play Game Services.");
#endif
            initializing = true;

            cloudSaveEnabled = activateCloudSave;

#if CLOUDONCE_DEBUG
            Debug.Log("Saved Games support " + (activateCloudSave ? "enabled." : "disabled."));
#endif
            var config = new PlayGamesClientConfiguration.Builder();
            if (activateCloudSave)
            {
                config.EnableSavedGames();
                CloudSaveInitialized = true;
            }

            PlayGamesPlatform.InitializeInstance(config.Build());

            SubscribeOnAuthenticatedEvent();

#if CLOUDONCE_DEBUG   // Enable/disable logs on the PlayGamesPlatform
            PlayGamesPlatform.DebugLogEnabled = true;
            Debug.Log("PlayGamesPlatform debug logs enabled.");
#else
            PlayGamesPlatform.DebugLogEnabled = false;
            Debug.Log("PlayGamesPlatform debug logs disabled.");
#endif
            IsGpgsInitialized = true;
            if (!IsGuestUserDefault && autoSignIn)
            {
                var onSignedIn = new UnityAction <bool>(arg0 =>
                {
                    cloudOnceEvents.RaiseOnInitializeComplete();
                    initializing = false;
                });
                SignIn(autoCloudLoad, onSignedIn);
            }
            else
            {
                if (IsGuestUserDefault && autoSignIn)
                {
                    Logger.d("Guest user mode active, ignoring auto sign-in. Please call SignIn directly.");
                }

                if (autoCloudLoad)
                {
                    cloudOnceEvents.RaiseOnCloudLoadComplete(false);
                }

                cloudOnceEvents.RaiseOnInitializeComplete();
                initializing = false;
            }
        }
Example #10
0
        // called from game thread
        public bool HasInvitationFromNotification()
        {
            bool has = mInvitationFromNotification != null;

            Logger.d("AndroidClient.HasInvitationFromNotification, returning " + has);
            return(has);
        }
 // called from game thread
 private void TbmpApiCall(string simpleDesc, string methodName,
                          Action <bool> callback, Action <bool, TurnBasedMatch> tbmpCallback,
                          params object[] args)
 {
     mClient.CallClientApi(simpleDesc, () => {
         ResultProxy proxy = new ResultProxy(this, methodName);
         if (callback != null)
         {
             proxy.SetSuccessCallback(callback);
         }
         if (tbmpCallback != null)
         {
             proxy.SetMatchCallback(tbmpCallback);
         }
         mClient.GHManager.CallGmsApiWithResult("games.Games", "TurnBasedMultiplayer",
                                                methodName, proxy, args);
     }, (bool success) => {
         if (!success)
         {
             Logger.w("Failed to " + simpleDesc + ": client disconnected.");
             if (callback != null)
             {
                 callback.Invoke(false);
             }
         }
     });
 }
        public void Finish(string matchId, byte[] data, MatchOutcome outcome, Action <bool> callback)
        {
            Logger.d(string.Format("AndroidTbmpClient.Finish matchId={0}, data={1} outcome={2}",
                                   matchId, data == null ? "(null)" : data.Length + " bytes", outcome));

            Logger.d("Preparing list of participant results as Android ArrayList.");
            AndroidJavaObject participantResults = new AndroidJavaObject("java.util.ArrayList");

            if (outcome != null)
            {
                foreach (string pid in outcome.ParticipantIds)
                {
                    Logger.d("Converting participant result to Android object: " + pid);
                    AndroidJavaObject thisParticipantResult = new AndroidJavaObject(
                        JavaConsts.ParticipantResultClass, pid,
                        JavaUtil.GetAndroidParticipantResult(outcome.GetResultFor(pid)),
                        outcome.GetPlacementFor(pid));

                    // (yes, the return type of ArrayList.add is bool, strangely)
                    Logger.d("Adding participant result to Android ArrayList.");
                    participantResults.Call <bool>("add", thisParticipantResult);
                    thisParticipantResult.Dispose();
                }
            }

            TbmpApiCall("tbmp finish w/ outcome", "finishMatch", callback, null,
                        matchId, data, participantResults);
        }
Example #13
0
 // called from game thread
 public Invitation GetInvitationFromNotification()
 {
     Logger.d("AndroidClient.GetInvitationFromNotification");
     Logger.d("Returning invitation: " + ((mInvitationFromNotification == null) ?
                                          "(null)" : mInvitationFromNotification.ToString()));
     return(mInvitationFromNotification);
 }
        public static void ShowSelectSnapshotUI(bool showCreateSaveUI, bool showDeleteSaveUI,
                                                int maxDisplayedSavedGames, string uiTitle, Action <SelectUIStatus, ISavedGameMetadata> cb)
        {
            using (var helperFragment = new AndroidJavaClass(HelperFragmentClass))
                using (var task = helperFragment.CallStatic <AndroidJavaObject>("showSelectSnapshotUi",
                                                                                GetActivity(), uiTitle, showCreateSaveUI, showDeleteSaveUI,
                                                                                maxDisplayedSavedGames))
                {
                    AndroidTaskUtils.AddOnSuccessListener <AndroidJavaObject>(
                        task,
                        result =>
                    {
                        var status = (SelectUIStatus)result.Get <int>("status");
                        Logger.d("ShowSelectSnapshotUI result " + status);

                        var javaMetadata = result.Get <AndroidJavaObject>("metadata");
                        var metadata     =
                            javaMetadata == null
                                ? null
                                : new AndroidSnapshotMetadata(javaMetadata, /* contents= */ null);

                        cb.Invoke(status, metadata);
                    });

                    AndroidTaskUtils.AddOnFailureListener(
                        task,
                        exception =>
                    {
                        Logger.e("ShowSelectSnapshotUI failed with exception");
                        cb.Invoke(SelectUIStatus.InternalError, null);
                    });
                }
        }
 /// <summary>
 /// Activates the Play Games platform as the implementation of Social.Active.
 /// After calling this method, you can call methods on Social.Active. For
 /// example, <c>Social.Active.Authenticate()</c>.
 /// </summary>
 /// <returns>The singleton <see cref="PlayGamesPlatform" /> instance.</returns>
 public static PlayGamesPlatform Activate()
 {
     Logger.d("Activating PlayGamesPlatform.");
     Social.Active = PlayGamesPlatform.Instance;
     Logger.d("PlayGamesPlatform activated: " + Social.Active);
     return(PlayGamesPlatform.Instance);
 }
Example #16
0
 internal void CallClientApi(string desc, Action call, Action <bool> callback)
 {
     Logger.d("Requesting API call: " + desc);
     RunWhenConnectionStable(() => {
         // we got a stable connection state to the games service
         // (either connected or disconnected, but not in progress).
         if (mGHManager.IsConnected())
         {
             // we are connected, so make the API call
             Logger.d("Connected! Calling API: " + desc);
             call.Invoke();
             if (callback != null)
             {
                 PlayGamesHelperObject.RunOnGameThread(() => {
                     callback.Invoke(true);
                 });
             }
         }
         else
         {
             // we are not connected, so fail the API call
             Logger.w("Not connected! Failed to call API :" + desc);
             if (callback != null)
             {
                 PlayGamesHelperObject.RunOnGameThread(() => {
                     callback.Invoke(false);
                 });
             }
         }
     });
 }
Example #17
0
        // called (on the UI thread) by GameHelperManager to notify us that sign in succeeded
        internal void OnSignInSucceeded()
        {
            Logger.d("AndroidClient got OnSignInSucceeded.");
            RetrieveUserInfo();

            if (mAuthState == AuthState.AuthPending || mAuthState == AuthState.InProgress)
            {
                Logger.d("AUTH: Auth succeeded. Proceeding to achievement loading.");
                DoInitialAchievementLoad();
            }
            else if (mAuthState == AuthState.LoadingAchs)
            {
                Logger.w("AUTH: Got OnSignInSucceeded() while in achievement loading phase (unexpected).");
                Logger.w("AUTH: Trying to fix by issuing a new achievement load call.");
                DoInitialAchievementLoad();
            }
            else
            {
                // we will hit this case during the normal lifecycle (for example, Activity
                // was brought to the foreground and sign in has succeeded even though
                // we were not in an auth flow).
                Logger.d("Normal lifecycle OnSignInSucceeded received.");
                RunPendingActions();

                // check for invitations that may have arrived via notification
                CheckForConnectionExtras();

                // inform the RTMP client that sign-in has suceeded
                mRtmpClient.OnSignInSucceeded();
                mTbmpClient.OnSignInSucceeded();
            }
        }
 /// <summary>
 /// Not implemented yet. Calls the callback with an empty list.
 /// </summary>
 public void LoadAchievements(Action <IAchievement[]> callback)
 {
     Logger.w("PlayGamesPlatform.LoadAchievements is not implemented.");
     if (callback != null)
     {
         callback.Invoke(new IAchievement[0]);
     }
 }
Example #19
0
 // called from game thread
 public void SubmitScore(string lbId, long score, Action <bool> callback)
 {
     Logger.d("AndroidClient.SubmitScore, lb=" + lbId + ", score=" + score);
     CallClientApi("submit score " + score + ", lb " + lbId, () => {
         mGHManager.CallGmsApi("games.Games", "Leaderboards",
                               "submitScore", lbId, score);
     }, callback);
 }
 /// <summary>
 /// Not implemented yet. Calls the callback with an empty list.
 /// </summary>
 public void LoadScores(string leaderboardID, Action <IScore[]> callback)
 {
     Logger.w("PlayGamesPlatform.LoadScores not implemented.");
     if (callback != null)
     {
         callback.Invoke(new IScore[0]);
     }
 }
Example #21
0
 // call from UI thread only!
 private void DoInitialAchievementLoad()
 {
     Logger.d("AUTH: Now performing initial achievement load...");
     mAuthState = AuthState.LoadingAchs;
     mGHManager.CallGmsApiWithResult("games.Games", "Achievements", "load",
                                     new OnAchievementsLoadedResultProxy(this), false);
     Logger.d("AUTH: Initial achievement load call made.");
 }
 /// <summary>
 /// Not implemented yet. Calls the callback with <c>false</c>.
 /// </summary>
 public void LoadScores(ILeaderboard board, Action <bool> callback)
 {
     Logger.w("PlayGamesPlatform.LoadScores not implemented.");
     if (callback != null)
     {
         callback.Invoke(false);
     }
 }
 /// <summary>
 /// Not implemented yet. Calls the callback with <c>false</c>.
 /// </summary>
 public void LoadFriends(ILocalUser user, Action <bool> callback)
 {
     Logger.w("PlayGamesPlatform.LoadFriends not implemented.");
     if (callback != null)
     {
         callback.Invoke(false);
     }
 }
 /// <summary>
 /// Not implemented yet. Calls the callback with an empty list.
 /// </summary>
 public void LoadUsers(string[] userIDs, Action <IUserProfile[]> callback)
 {
     Logger.w("PlayGamesPlatform.LoadUsers is not implemented.");
     if (callback != null)
     {
         callback.Invoke(new IUserProfile[0]);
     }
 }
 // called on UI thread
 public void OnSignInSucceeded()
 {
     Logger.d("AndroidTbmpClient.OnSignInSucceeded");
     Logger.d("Querying for max match data size...");
     mMaxMatchDataSize = mClient.GHManager.CallGmsApi <int>("games.Games",
                                                            "TurnBasedMultiplayer", "getMaxMatchDataSize");
     Logger.d("Max match data size: " + mMaxMatchDataSize);
 }
 public void LeaveDuringTurn(string matchId, string pendingParticipantId,
                             Action <bool> callback)
 {
     Logger.d("AndroidTbmpClient.LeaveDuringTurn, matchId=" + matchId + ", pending=" +
              pendingParticipantId);
     TbmpApiCall("tbmp leave during turn", "leaveMatchDuringTurn", callback, null, matchId,
                 pendingParticipantId);
 }
Example #27
0
 // called from game thread
 public void LoadState(int slot, OnStateLoadedListener listener)
 {
     Logger.d("AndroidClient.LoadState, slot=" + slot);
     CallClientApi("load state slot=" + slot, () => {
         OnStateResultProxy proxy = new OnStateResultProxy(this, listener);
         mGHManager.CallGmsApiWithResult("appstate.AppStateManager", null, "load",
                                         proxy, slot);
     }, null);
 }
 /// <summary>
 /// Sets the default leaderboard for the leaderboard UI. After calling this
 /// method, a call to <see cref="ShowLeaderboardUI" /> will show only the specified
 /// leaderboard instead of showing the list of all leaderboards.
 /// </summary>
 /// <param name='lbid'>
 /// The ID of the leaderboard to display on the default UI. This may be a raw
 /// Google Play Games leaderboard ID or an alias configured through a call to
 /// <see cref="AddIdMapping" />.
 /// </param>
 public void SetDefaultLeaderboardForUI(string lbid)
 {
     Logger.d("SetDefaultLeaderboardForUI: " + lbid);
     if (lbid != null)
     {
         lbid = MapId(lbid);
     }
     mDefaultLbUi = lbid;
 }
 /// <summary>
 /// Returns the user's display name.
 /// </summary>
 /// <returns>
 /// The user display name (e.g. "Bruno Oliveira")
 /// </returns>
 public string GetUserDisplayName()
 {
     if (!IsAuthenticated())
     {
         Logger.e("GetUserDisplayName can only be called after authentication.");
         return("");
     }
     return(mClient.GetUserDisplayName());
 }
Example #30
0
 private void RegisterInvitationListener()
 {
     Logger.d("AndroidClient.RegisterInvitationListener");
     CallClientApi("register invitation listener", () => {
         mGHManager.CallGmsApi("games.Games", "Invitations",
                               "registerInvitationListener", new OnInvitationReceivedProxy(this));
     }, null);
     mRegisteredInvitationListener = true;
 }