private void CheckForConnectionExtras() { // check to see if we have a pending invitation in our gamehelper Logger.d("AndroidClient: CheckInvitationFromNotification."); Logger.d("AndroidClient: looking for invitation in our GameHelper."); Invitation invFromNotif = null; AndroidJavaObject invObj = mGHManager.GetInvitation(); AndroidJavaObject matchObj = mGHManager.GetTurnBasedMatch(); mGHManager.ClearInvitationAndTurnBasedMatch(); if (invObj != null) { Logger.d("Found invitation in GameHelper. Converting."); invFromNotif = ConvertInvitation(invObj); Logger.d("Found invitation in our GameHelper: " + invFromNotif); } else { Logger.d("No invitation in our GameHelper. Trying SignInHelperManager."); AndroidJavaClass cls = JavaUtil.GetClass(JavaConsts.SignInHelperManagerClass); using (AndroidJavaObject inst = cls.CallStatic <AndroidJavaObject>("getInstance")) { if (inst.Call <bool>("hasInvitation")) { invFromNotif = ConvertInvitation(inst.Call <AndroidJavaObject>("getInvitation")); Logger.d("Found invitation in SignInHelperManager: " + invFromNotif); inst.Call("forgetInvitation"); } else { Logger.d("No invitation in SignInHelperManager either."); } } } TurnBasedMatch match = null; if (matchObj != null) { Logger.d("Found match in GameHelper. Converting."); match = JavaUtil.ConvertMatch(mUserId, matchObj); Logger.d("Match from GameHelper: " + match); } else { Logger.d("No match in our GameHelper. Trying SignInHelperManager."); AndroidJavaClass cls = JavaUtil.GetClass(JavaConsts.SignInHelperManagerClass); using (AndroidJavaObject inst = cls.CallStatic <AndroidJavaObject>("getInstance")) { if (inst.Call <bool>("hasTurnBasedMatch")) { match = JavaUtil.ConvertMatch(mUserId, inst.Call <AndroidJavaObject>("getTurnBasedMatch")); Logger.d("Found match in SignInHelperManager: " + match); inst.Call("forgetTurnBasedMatch"); } else { Logger.d("No match in SignInHelperManager either."); } } } // if we got an invitation from the notification, invoke the delegate if (invFromNotif != null) { if (mInvitationDelegate != null) { Logger.d("Invoking invitation received delegate to deal with invitation " + " from notification."); PlayGamesHelperObject.RunOnGameThread(() => { if (mInvitationDelegate != null) { mInvitationDelegate.Invoke(invFromNotif, true); } }); } else { Logger.d("No delegate to handle invitation from notification; queueing."); mInvitationFromNotification = invFromNotif; } } // if we got a turn-based match, hand it over to the TBMP client who will know // better what to do with it if (match != null) { mTbmpClient.HandleMatchFromNotification(match); } }
public static TurnBasedMatch ConvertMatch(string playerId, AndroidJavaObject matchObj) { List <AndroidJavaObject> toDispose = new List <AndroidJavaObject>(); Logger.d("AndroidTbmpClient.ConvertMatch, playerId=" + playerId); string matchId; byte[] data; bool canRematch; int availableAutomatchSlots; string selfParticipantId; List <Participant> participants = new List <Participant>(); string pendingParticipantId; TurnBasedMatch.MatchTurnStatus turnStatus; TurnBasedMatch.MatchStatus matchStatus; int variant; matchId = matchObj.Call <string>("getMatchId"); AndroidJavaObject dataObj = JavaUtil.CallNullSafeObjectMethod(matchObj, "getData"); toDispose.Add(dataObj); data = JavaUtil.ConvertByteArray(dataObj); canRematch = matchObj.Call <bool>("canRematch"); availableAutomatchSlots = matchObj.Call <int>("getAvailableAutoMatchSlots"); selfParticipantId = matchObj.Call <string>("getParticipantId", playerId); AndroidJavaObject participantIds = matchObj.Call <AndroidJavaObject>("getParticipantIds"); toDispose.Add(participantIds); int participantCount = participantIds.Call <int>("size"); for (int i = 0; i < participantCount; i++) { string thisId = participantIds.Call <string>("get", i); AndroidJavaObject thisPart = matchObj.Call <AndroidJavaObject>("getParticipant", thisId); toDispose.Add(thisPart); Participant p = JavaUtil.ConvertParticipant(thisPart); participants.Add(p); } pendingParticipantId = matchObj.Call <string>("getPendingParticipantId"); turnStatus = JavaUtil.ConvertTurnStatus(matchObj.Call <int>("getTurnStatus")); matchStatus = JavaUtil.ConvertMatchStatus(matchObj.Call <int>("getStatus")); variant = matchObj.Call <int>("getVariant"); // cleanup foreach (AndroidJavaObject obj in toDispose) { if (obj != null) { obj.Dispose(); } } // participants should be sorted by participant ID participants.Sort(); return(new TurnBasedMatch(matchId, data, canRematch, selfParticipantId, participants, availableAutomatchSlots, pendingParticipantId, turnStatus, matchStatus, variant)); }
// called from UI thread private void UpdateRoom() { List <AndroidJavaObject> toDispose = new List <AndroidJavaObject>(); Logger.d("UpdateRoom: Updating our cached data about the room."); string roomId = mRoom.Call <string>("getRoomId"); Logger.d("UpdateRoom: room id: " + roomId); Logger.d("UpdateRoom: querying for my player ID."); string playerId = mClient.GHManager.CallGmsApi <string>("games.Games", "Players", "getCurrentPlayerId"); Logger.d("UpdateRoom: my player ID is: " + playerId); Logger.d("UpdateRoom: querying for my participant ID in the room."); string myPartId = mRoom.Call <string>("getParticipantId", playerId); Logger.d("UpdateRoom: my participant ID is: " + myPartId); AndroidJavaObject participantIds = mRoom.Call <AndroidJavaObject>("getParticipantIds"); toDispose.Add(participantIds); int participantCount = participantIds.Call <int>("size"); Logger.d("UpdateRoom: # participants: " + participantCount); List <Participant> connectedParticipants = new List <Participant>(); List <Participant> allParticipants = new List <Participant>(); mSelf = null; for (int i = 0; i < participantCount; i++) { Logger.d("UpdateRoom: querying participant #" + i); string thisId = participantIds.Call <string>("get", i); Logger.d("UpdateRoom: participant #" + i + " has id: " + thisId); AndroidJavaObject thisPart = mRoom.Call <AndroidJavaObject>("getParticipant", thisId); toDispose.Add(thisPart); Participant p = JavaUtil.ConvertParticipant(thisPart); allParticipants.Add(p); if (p.ParticipantId.Equals(myPartId)) { Logger.d("Participant is SELF."); mSelf = p; } if (p.IsConnectedToRoom) { connectedParticipants.Add(p); } } if (mSelf == null) { Logger.e("List of room participants did not include self, " + " participant id: " + myPartId + ", player id: " + playerId); // stopgap: mSelf = new Participant("?", myPartId, Participant.ParticipantStatus.Unknown, new GooglePlayGames.BasicApi.Multiplayer.Player("?", playerId), false); } connectedParticipants.Sort(); allParticipants.Sort(); string[] newlyConnected; string[] newlyDisconnected; // lock the list because it's read by the game thread lock (mParticipantListsLock) { newlyConnected = SubtractParticipants(connectedParticipants, mConnectedParticipants); newlyDisconnected = SubtractParticipants(mConnectedParticipants, connectedParticipants); // IMPORTANT: we treat mConnectedParticipants as an immutable list; we give // away references to it to the callers of our API, so anyone out there might // be holding a reference to it and reading it from any thread. // This is why, instead of modifying it in place, we assign a NEW list to it. mConnectedParticipants = connectedParticipants; mAllParticipants = allParticipants; Logger.d("UpdateRoom: participant list now has " + mConnectedParticipants.Count + " participants."); } // cleanup Logger.d("UpdateRoom: cleanup."); foreach (AndroidJavaObject obj in toDispose) { obj.Dispose(); } Logger.d("UpdateRoom: newly connected participants: " + newlyConnected.Length); Logger.d("UpdateRoom: newly disconnected participants: " + newlyDisconnected.Length); // only deliver peers connected/disconnected events if have delivered OnRoomConnected if (mDeliveredRoomConnected) { if (newlyConnected.Length > 0 && mRtmpListener != null) { Logger.d("UpdateRoom: calling OnPeersConnected callback"); mRtmpListener.OnPeersConnected(newlyConnected); } if (newlyDisconnected.Length > 0 && mRtmpListener != null) { Logger.d("UpdateRoom: calling OnPeersDisconnected callback"); mRtmpListener.OnPeersDisconnected(newlyDisconnected); } } // did the developer request to leave the room? if (mLeaveRoomRequested) { Clear("deferred leave-room request"); } // is it time to report progress during room setup? if (!mDeliveredRoomConnected) { DeliverRoomSetupProgressUpdate(); } }
private void CheckForConnectionExtras() { Logger.d("AndroidClient: CheckInvitationFromNotification."); Logger.d("AndroidClient: looking for invitation in our GameHelper."); Invitation invFromNotif = null; AndroidJavaObject invitation = this.mGHManager.GetInvitation(); AndroidJavaObject turnBasedMatch = this.mGHManager.GetTurnBasedMatch(); this.mGHManager.ClearInvitationAndTurnBasedMatch(); if (invitation != null) { Logger.d("Found invitation in GameHelper. Converting."); invFromNotif = this.ConvertInvitation(invitation); Logger.d("Found invitation in our GameHelper: " + invFromNotif); } else { Logger.d("No invitation in our GameHelper. Trying SignInHelperManager."); AndroidJavaClass @class = JavaUtil.GetClass("com.google.example.games.pluginsupport.SignInHelperManager"); using (AndroidJavaObject androidJavaObject = @class.CallStatic <AndroidJavaObject>("getInstance", new object[0])) { if (androidJavaObject.Call <bool>("hasInvitation", new object[0])) { invFromNotif = this.ConvertInvitation(androidJavaObject.Call <AndroidJavaObject>("getInvitation", new object[0])); Logger.d("Found invitation in SignInHelperManager: " + invFromNotif); androidJavaObject.Call("forgetInvitation", new object[0]); } else { Logger.d("No invitation in SignInHelperManager either."); } } } TurnBasedMatch turnBasedMatch2 = null; if (turnBasedMatch != null) { Logger.d("Found match in GameHelper. Converting."); turnBasedMatch2 = JavaUtil.ConvertMatch(this.mUserId, turnBasedMatch); Logger.d("Match from GameHelper: " + turnBasedMatch2); } else { Logger.d("No match in our GameHelper. Trying SignInHelperManager."); AndroidJavaClass class2 = JavaUtil.GetClass("com.google.example.games.pluginsupport.SignInHelperManager"); using (AndroidJavaObject androidJavaObject2 = class2.CallStatic <AndroidJavaObject>("getInstance", new object[0])) { if (androidJavaObject2.Call <bool>("hasTurnBasedMatch", new object[0])) { turnBasedMatch2 = JavaUtil.ConvertMatch(this.mUserId, androidJavaObject2.Call <AndroidJavaObject>("getTurnBasedMatch", new object[0])); Logger.d("Found match in SignInHelperManager: " + turnBasedMatch2); androidJavaObject2.Call("forgetTurnBasedMatch", new object[0]); } else { Logger.d("No match in SignInHelperManager either."); } } } if (invFromNotif != null) { if (this.mInvitationDelegate != null) { Logger.d("Invoking invitation received delegate to deal with invitation from notification."); PlayGamesHelperObject.RunOnGameThread(delegate { if (this.mInvitationDelegate != null) { this.mInvitationDelegate(invFromNotif, true); } }); } else { Logger.d("No delegate to handle invitation from notification; queueing."); this.mInvitationFromNotification = invFromNotif; } } if (turnBasedMatch2 != null) { this.mTbmpClient.HandleMatchFromNotification(turnBasedMatch2); } }
internal GameHelperManager(AndroidClient client) { mAndroidClient = client; Logger.d("Setting up GameHelperManager."); // create GameHelper Logger.d("GHM creating GameHelper."); int flags = JavaConsts.GAMEHELPER_CLIENT_ALL; Logger.d("GHM calling GameHelper constructor with flags=" + flags); mGameHelper = new AndroidJavaObject(GameHelperClass, mAndroidClient.GetActivity(), flags); if (mGameHelper == null) { throw new System.Exception("Failed to create GameHelper."); } // set up the GameHelper Logger.d("GHM setting up GameHelper."); mGameHelper.Call("enableDebugLog", Logger.DebugLogEnabled, "GameHelper"); GameHelperListener listenerProxy = new GameHelperListener(this, ORIGIN_MAIN_ACTIVITY); // IMPORTANT: we need to tweak the default behavior of GameHelper because // it should never attempt to automatically start the // sign in flow, because this must be done by the SignInActivity! This // is why we call setMaxAutoSignInAttempts(0). This is important because if THIS // GameHelper were to attempt the sign-in flow, nothing would work, because // it needs onActivityResult to be hooked up, and we have no way to access // onActivityResult on the Unity player activity. This is why we use a separate // Activity for the sign in flow. Logger.d("GHM Setting GameHelper options."); mGameHelper.Call("setMaxAutoSignInAttempts", 0); AndroidJavaClass gameOptionsClass = JavaUtil.GetGmsClass("games.Games$GamesOptions"); AndroidJavaObject builder = gameOptionsClass.CallStatic <AndroidJavaObject>("builder"); AndroidJavaObject tmp = builder.Call <AndroidJavaObject>("setSdkVariant", JavaConsts.SDK_VARIANT); AndroidJavaObject options = builder.Call <AndroidJavaObject>("build"); mGameHelper.Call("setGamesApiOptions", options); options.Dispose(); options = null; tmp.Dispose(); tmp = null; builder.Dispose(); builder = null; Logger.d("GHM calling GameHelper.setup"); mGameHelper.Call("setup", listenerProxy); Logger.d("GHM: GameHelper setup done."); // set up callbacks so we're informed of pause/unpause events Logger.d("GHM Setting up lifecycle."); PlayGamesHelperObject.SetPauseCallback((bool paused) => { if (paused) { OnPause(); } else { OnResume(); } }); // start initial auth Logger.d("GHM calling GameHelper.onStart to try initial auth."); mConnectionState = ConnectionState.Connecting; mGameHelper.Call("onStart", mAndroidClient.GetActivity()); }
public override byte[] readFully() { AndroidJavaObject byteArrayObj = mObj.Call <AndroidJavaObject>("readFully"); return(JavaUtil.ConvertByteArray(byteArrayObj)); }
internal void ProcessBuffer(AndroidJavaObject questBuffer) { int i, count; Logger.d("QuestBank: processing quest buffer given as Java object."); if (questBuffer == null) { Logger.w("QuestBank: given buffer was null. Ignoring."); return; } count = questBuffer.Call <int>("getCount"); Logger.d("QuestBank: buffer contains " + count + " quests."); for (i = 0; i < count; ++i) { Logger.d("QuestBank: processing quest #" + i); Quest quest = new Quest(); AndroidJavaObject questObj = questBuffer.Call <AndroidJavaObject>("get", i); if (questObj == null) { Logger.w("Quest #" + i + " was null. Ignoring."); continue; } quest.Id = questObj.Call <string>("getQuestId"); quest.Name = questObj.Call <string>("getName"); quest.Description = questObj.Call <string>("getDescription"); quest.StartTimestamp = questObj.Call <long>("getStartTimestamp"); quest.AcceptedTimestamp = questObj.Call <long>("getAcceptedTimestamp"); quest.EndTimestamp = questObj.Call <long>("getEndTimestamp"); quest.State = questObj.Call <int>("getState"); AndroidJavaObject mileObj = JavaUtil.CallNullSafeObjectMethod(questObj, "getCurrentMilestone"); if (mileObj != null) { Milestone milestone = new Milestone(); milestone.Id = mileObj.Call <string>("getMilestoneId"); milestone.EventId = mileObj.Call <string>("getEventId"); milestone.CurrentProgress = mileObj.Call <long>("getCurrentProgress"); milestone.TargetProgress = mileObj.Call <long>("getTargetProgress"); milestone.CompletionRewardData = mileObj.Call <byte[]>("getCompletionRewardData"); milestone.State = mileObj.Call <int>("getState"); quest.Milestone = milestone; } Logger.d("QuestBank: processed: " + quest.ToString()); if (quest.Milestone != null) { Logger.d("QuestBank: milestone: " + quest.Milestone.ToString()); } if (quest.Id != null && quest.Id.Length > 0) { mQuests[quest.Id] = quest; } else { Logger.w("Quest w/ missing ID received. Ignoring."); } } Logger.d("QuestBank: bank now contains " + mQuests.Count + " entries."); }
public void onResult(AndroidJavaObject result) { Logger.d("ResultProxy got result for method: " + this.mMethod); int statusCode = JavaUtil.GetStatusCode(result); bool isSuccess = this.mSuccessCodes.Contains(statusCode); TurnBasedMatch match = null; if (isSuccess) { Logger.d(string.Concat(new object[] { "SUCCESS result from method ", this.mMethod, ": ", statusCode })); if (this.mMatchCallback != null) { Logger.d("Attempting to get match from result of " + this.mMethod); AndroidJavaObject androidJavaObject = JavaUtil.CallNullSafeObjectMethod(result, "getMatch", new object[0]); if (androidJavaObject != null) { Logger.d("Successfully got match from result of " + this.mMethod); match = JavaUtil.ConvertMatch(this.mOwner.mClient.PlayerId, androidJavaObject); androidJavaObject.Dispose(); } else { Logger.w("Got a NULL match from result of " + this.mMethod); } } } else { Logger.w(string.Concat(new object[] { "ERROR result from ", this.mMethod, ": ", statusCode })); } if (this.mSuccessCallback != null) { Logger.d(string.Concat(new object[] { "Invoking success callback (success=", isSuccess, ") for result of method ", this.mMethod })); PlayGamesHelperObject.RunOnGameThread(delegate { this.mSuccessCallback(isSuccess); }); } if (this.mMatchCallback != null) { Logger.d(string.Concat(new object[] { "Invoking match callback for result of method ", this.mMethod, ": (success=", isSuccess, ", match=", (match != null) ? match.ToString() : "(null)" })); PlayGamesHelperObject.RunOnGameThread(delegate { this.mMatchCallback(isSuccess, match); }); } }
internal GameHelperManager(AndroidClient client) { this.mAndroidClient = client; Logger.d("Setting up GameHelperManager."); Logger.d("GHM creating GameHelper."); int num = 7; Logger.d("GHM calling GameHelper constructor with flags=" + num); this.mGameHelper = new AndroidJavaObject("com.google.example.games.basegameutils.GameHelper", new object[] { this.mAndroidClient.GetActivity(), num }); if (this.mGameHelper == null) { throw new Exception("Failed to create GameHelper."); } Logger.d("GHM setting up GameHelper."); this.mGameHelper.Call("enableDebugLog", new object[] { Logger.DebugLogEnabled }); GameHelperManager.GameHelperListener gameHelperListener = new GameHelperManager.GameHelperListener(this, 1000); Logger.d("GHM Setting GameHelper options."); this.mGameHelper.Call("setMaxAutoSignInAttempts", new object[] { 0 }); AndroidJavaClass gmsClass = JavaUtil.GetGmsClass("games.Games$GamesOptions"); AndroidJavaObject androidJavaObject = gmsClass.CallStatic <AndroidJavaObject>("builder", new object[0]); AndroidJavaObject androidJavaObject2 = androidJavaObject.Call <AndroidJavaObject>("setSdkVariant", new object[] { 37143 }); AndroidJavaObject androidJavaObject3 = androidJavaObject.Call <AndroidJavaObject>("build", new object[0]); this.mGameHelper.Call("setGamesApiOptions", new object[] { androidJavaObject3 }); androidJavaObject3.Dispose(); androidJavaObject2.Dispose(); androidJavaObject.Dispose(); Logger.d("GHM calling GameHelper.setup"); this.mGameHelper.Call("setup", new object[] { gameHelperListener }); Logger.d("GHM: GameHelper setup done."); Logger.d("GHM Setting up lifecycle."); PlayGamesHelperObject.SetPauseCallback(delegate(bool paused) { if (paused) { this.OnPause(); } else { this.OnResume(); } }); Logger.d("GHM calling GameHelper.onStart to try initial auth."); this.mGameHelper.Call("onStart", new object[] { this.mAndroidClient.GetActivity() }); }
public static AndroidJavaClass GetGmsClass(string className) { return(JavaUtil.GetClass("com.google.android.gms." + className)); }
private void UpdateRoom() { List <AndroidJavaObject> list = new List <AndroidJavaObject>(); Logger.d("UpdateRoom: Updating our cached data about the room."); string str = this.mRoom.Call <string>("getRoomId", new object[0]); Logger.d("UpdateRoom: room id: " + str); Logger.d("UpdateRoom: querying for my player ID."); string text = this.mClient.GHManager.CallGmsApi <string>("games.Games", "Players", "getCurrentPlayerId", new object[0]); Logger.d("UpdateRoom: my player ID is: " + text); Logger.d("UpdateRoom: querying for my participant ID in the room."); string text2 = this.mRoom.Call <string>("getParticipantId", new object[] { text }); Logger.d("UpdateRoom: my participant ID is: " + text2); AndroidJavaObject androidJavaObject = this.mRoom.Call <AndroidJavaObject>("getParticipantIds", new object[0]); list.Add(androidJavaObject); int num = androidJavaObject.Call <int>("size", new object[0]); Logger.d("UpdateRoom: # participants: " + num); List <Participant> list2 = new List <Participant>(); List <Participant> list3 = new List <Participant>(); this.mSelf = null; for (int i = 0; i < num; i++) { Logger.d("UpdateRoom: querying participant #" + i); string text3 = androidJavaObject.Call <string>("get", new object[] { i }); Logger.d(string.Concat(new object[] { "UpdateRoom: participant #", i, " has id: ", text3 })); AndroidJavaObject androidJavaObject2 = this.mRoom.Call <AndroidJavaObject>("getParticipant", new object[] { text3 }); list.Add(androidJavaObject2); Participant participant = JavaUtil.ConvertParticipant(androidJavaObject2); list3.Add(participant); if (participant.ParticipantId.Equals(text2)) { Logger.d("Participant is SELF."); this.mSelf = participant; } if (participant.IsConnectedToRoom) { list2.Add(participant); } } if (this.mSelf == null) { Logger.e("List of room participants did not include self, participant id: " + text2 + ", player id: " + text); this.mSelf = new Participant("?", text2, Participant.ParticipantStatus.Unknown, new Player("?", text), false); } list2.Sort(); list3.Sort(); object obj = this.mParticipantListsLock; string[] array; string[] array2; lock (obj) { array = this.SubtractParticipants(list2, this.mConnectedParticipants); array2 = this.SubtractParticipants(this.mConnectedParticipants, list2); this.mConnectedParticipants = list2; this.mAllParticipants = list3; Logger.d("UpdateRoom: participant list now has " + this.mConnectedParticipants.Count + " participants."); } Logger.d("UpdateRoom: cleanup."); foreach (AndroidJavaObject current in list) { current.Dispose(); } Logger.d("UpdateRoom: newly connected participants: " + array.Length); Logger.d("UpdateRoom: newly disconnected participants: " + array2.Length); if (this.mDeliveredRoomConnected) { if (array.Length > 0 && this.mRtmpListener != null) { Logger.d("UpdateRoom: calling OnPeersConnected callback"); this.mRtmpListener.OnPeersConnected(array); } if (array2.Length > 0 && this.mRtmpListener != null) { Logger.d("UpdateRoom: calling OnPeersDisconnected callback"); this.mRtmpListener.OnPeersDisconnected(array2); } } if (this.mLeaveRoomRequested) { this.Clear("deferred leave-room request"); } if (!this.mDeliveredRoomConnected) { this.DeliverRoomSetupProgressUpdate(); } }