Issue connecting to play game using game center - ios

I am facing the issue of Multiplayer Invitation endless Processing below is the detail.
open func player(_ player: GKPlayer, didAccept inviteToAccept: GKInvite) {
print("player is \(player) \nInvite is \(inviteToAccept)")
EGC.guestPlayerIdentifier = player.playerID
guard let gkmv = GKMatchmakerViewController(invite: inviteToAccept) else {
EGCError.error("GKMatchmakerViewController invite to accept nil").errorCall()
return
}
gkmv.matchmakerDelegate = self
var delegeteParent:UIViewController? = EGC.delegate.parent
if delegeteParent == nil {
delegeteParent = EGC.delegate
}
delegeteParent!.present(gkmv, animated: true, completion: nil)
}
On average only 1 out of 5 tries would they be able to connect & play a
full match.
If one of them invited another who had the game open on his phone
he would get the invite and game would start but for the other, the game
would be blank or endlessly processing. However, if the invited didn't
have his game opened already it seemed to work more often. any help would be appreciated
.

Related

Incoming GameCenter invite contains no players

I’m trying to get my game to allow 1 device (iPhone) to use GameCenter to invite a friend to play (iPad). I’m using the standard/default MatchMaker interface. The iPhone sends the invitation to the iPad which presents a notification.
When I press this notification the iPad’s ‘player(GKPlayer, didAccept: GKInvite)’ routine DOES get called.
#objc func player(_ playerMe: GKPlayer, didAccept invite: GKInvite) {
print("\n\n\t\tplayer \(playerMe.displayName)(\(playerMe.playerID)) did accept INVITE sent by \(invite.sender.displayName)(\(invite.sender.playerID))")
GKMatchmaker.shared().match(for: invite, completionHandler: {(InvitedMatch, error) in
print("\t\tplayers.count = \(InvitedMatch!.players.count)")
if error != nil {
print("INVITE ERROR: \(error.debugDescription)")
}
if InvitedMatch != nil {
print("\t\tSetting current match. (\(InvitedMatch.debugDescription))")
self.currentMatch = InvitedMatch
self.currentMatch?.delegate = self
// self.prepareMatch()
}
})
}
Output:
player Me(G:25139341913) did accept INVITE sent by ‎“-----”(G:12453976)
players.count = 0
Setting current match. (Optional(<GKMatch 0x282d39970 expected count: 1 seqnum: 0
G:12453976:unknown
reinvitedPlayers:(
)>))
The players array is EMPTY! Shouldn’t it at least have the inviter in there? The ‘expectedPlayerCount’ properly reflects 2 person matchRequest where 1 player (the inviter) is already a participant)
At no point was the ‘player(GKPlayer, didRequestMatchWithRecipients: [GKPlayer])’ called by either end.
So the iPad doesn’t have access to the players to setup the match, but the iPhone sees that the invitation was accepted, has 2 players, and moves on. The iPhone code:
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
print("\n\n\t\tMATCH FOUND\n\n")
viewController.dismiss(animated: true, completion: nil)
GKMatchmaker.shared().stopBrowsingForNearbyPlayers()
currentMatch = match
match.delegate = self
if Globals.gameState?.currentState is StateWaitingForMatch {
if currentMatch?.expectedPlayerCount == 0 {
prepareMatch()
}
}
}
So how do I get the iPad (recipient of the invitation) to see/include the players?
In the player(GKPlayer, invite: GKInvite) method create a GKMatchMakerViewController via
let mmvc = GKMatchmakerViewController(invite: invite!)
and then present it:
viewController.present(mmvc!, animated: true, completion: nil)

Game Center Group Leaderboard issue

I have an iOS game with one Game Center leaderboard. Recently I published the game and it works fine with no issues. Then I did light version of the game and I'd like to use the same leaderboard for both games. I combined both versions of the game into the Game Center group and modified leaderboard ID, because Apple requires to start group leaderboard names with grp..
Now, if I load scores I receive nil. But if I firstly submit some score and load after that I receive only score for the local player. I checked the leaderboard on itunesconnect and I know for sure that there are a lot of records in the leaderboard. The leaderboard is the same as it was before combining into the group. I thought that Game Center needs some time to update, but I've waited about one day still see no changing.
So my question is why I received nil or score only for local player? Do I do something wrong? Or this is just a Game Center bug?
I found some similar issues here but the most recent one was posted about two years ago. Does anyone have any ideas? Any help appreciated!
Here is my code to load scores:
func loadScores(){
let leaderboard = GKLeaderboard()
leaderboard.identifier = "grp.myLeaderboardID"
leaderboard.loadScores { (scores, error) in
if error != nil {
print(error!.localizedDescription)
} else {
//do something with the scores
}
}
}
}
and to sumbit scores:
func submitScore(value: Int64) {
let leaderboardID = "grp.myLeaderboardID"
let sRating = GKScore(leaderboardIdentifier: leaderboardID)
sRating.value = value
GKScore.report([sRating], withCompletionHandler: { (error: Error?) -> Void in
if error != nil {
print(error!.localizedDescription)
}
})
}
UPDATE.
The problem has gone suddenly. I think that the issue has been dealt with apple server bug but with combining into a group

Show GameCenter login later if user dismisses login screen at start of game?

We present the GameCenter login screen upon the game's launch. At the end of the game, we show a GameCenter button that lets users view their achievements and the game's leaderboards. If they dismissed the original screen and aren't logged in, how can we present the login screen again? Here's the code we're using, but it's not working.
override func viewDidLoad() {
super.viewDidLoad()
// Configure view
let skView = view as! SKView
skView.multipleTouchEnabled = false
//skView.showsNodeCount = true
//skView.showsFPS = true
// Show intro scene
let introScene = IntroScene(size: skView.bounds.size, controller: self)
introScene.scaleMode = .AspectFill
skView.presentScene(introScene)
// Authenticate GameCenter player
authenticateGameCenterPlayer()
}
private func authenticateGameCenterPlayer() {
var localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {(viewController : UIViewController!, error : NSError!) -> Void in
if ((viewController) != nil) {
self.presentViewController(viewController, animated: true, completion: nil)
} else {
println((GKLocalPlayer.localPlayer().authenticated))
}
}
}
func showLeaderboard() {
// User logged into GameCenter?
if (!GKLocalPlayer.localPlayer().authenticated) {
println("Local player not authenticated")
authenticateGameCenterPlayer()
return
}
// If here, user is authenticated so present leaderboards
var gcViewController = GKGameCenterViewController()
gcViewController.gameCenterDelegate = self
gcViewController.viewState = GKGameCenterViewControllerState.Leaderboards
gcViewController.leaderboardIdentifier = "highScoresLeaderboard"
self.showViewController(gcViewController, sender: self)
self.navigationController?.pushViewController(gcViewController, animated: true)
}
I understand Apple documentation mentions this in the the Game Center Programming Guide under Common Tasks When Working with Players > Authenticating a Local Player on the Device.
Important: Game Kit handles opting out of Game Center across all games
that support Game Center. If a player has already declined to create
an account, when your game authenticates the player, it is told there
is no authenticated player. The player never sees an authentication
dialog. Because Game Kit handles this process across all games, your
game should not include its own mechanism to disable Game Center
authentication or ask a player’s permission to authenticate. Instead,
your game should simply authenticate the player every time it launches
and respond appropriately when authentication completes
.
Game Center remembers the users log-in preferences and if the user dismisses the log-in dialog too many times, it will stop being displayed, even when you call localPlayer.authenticateHandler
The recommended way of handling this is to display a message telling the user to log in through the game center app
Almost a year late, but I encountered a similar issue and implemented a type of work around.
Check to see if the user is authenticated, and if not direct them to use the game center deeplink. This will prompt the login screen.
UIApplication.sharedApplication().openURL(NSURL(string: "gamecenter:")!)
If a user chooses not to login, they will be redirected back to your app. If a user logs in, they will have the ability to navigate back to your app via the back "Back to App" button at the top.

How do you implement shared GKMatchmaker's findMatchForRequest correctly (so GKMatch.expectedPlayerCount == 0)?

When switching to GKMatchmaker from MatchmakerViewController my two sandbox game center accounts running on separate devices (both iPhone 5s) no longer connect into the same match. Both show expectedPlayerCount still above 0.
I followed the RayWenderlich tutorial on creating a multiplayer game with game center. It is supposed to be real time and was working as such. Using a GKMatchmakerViewController it all worked completely fine (both auto-matching and invites). However, as soon as I switched one block of code it no longer works. I've been fiddling with this for awhile now and the apple docs don't seem to help me at all. Anyone know what I might need to do extra?
func findMatchWithMinPlayers(minPlayers: Int, maxPlayers: Int, viewController: UIViewController, delegate: GameKitHelperDelegate) {
if enableGameCenter == false {
return
}
matchStarted = false
gkMatch = nil
gkDelegate = delegate
viewController.dismissViewControllerAnimated(false, completion: nil)
var request = GKMatchRequest()
request.minPlayers = minPlayers
request.maxPlayers = maxPlayers
if pendingRecipients != nil {
request.recipients = pendingRecipients!
}
GKMatchmaker.sharedMatchmaker().findMatchForRequest(request, withCompletionHandler: { (match: GKMatch!, error: NSError!) -> Void in
self.gkMatch = match
self.gkMatch?.delegate = self
println(match)
if self.matchStarted == false && match.expectedPlayerCount == 0 {
self.lookupPlayers()
}
})
}
This only difference between this and what was working is that this has the GKMatchmaker instead of the GKMatchmakerViewController and Delegate.

startBrowsingForNearbyPlayersWithHandler() in iOS 8 in Swift

I'm currently making a 2-player strategy board game in Swift and need to connect two iPads over local WiFi or Bluetooth. No matter what I've tried today, I can't get them to detect each other (I've tried over local WiFi and Bluetooth).
Here is my authorization code which runs in the UIViewController when my app first launches (which always returns "Self local player is authenticated." along with the ID:
private func authenticateLocalPlayer() {
var localPlayer = getLocalPlayer()
// If Apple were doing their job right, this is what the proper code should look like:
// var localPlayer = GKLocalPlayer.localPlayer()
if ( !localPlayer.authenticated ) {
localPlayer.authenticateHandler = { (viewController : UIViewController!, error : NSError!) -> Void in
NSLog("Error: \(error)")
if viewController != nil {
// Authenticated?
self.presentViewController(viewController, animated: true, completion: nil)
NSLog("viewController is not nil")
} else if (localPlayer.authenticated == true) {
NSLog("Self local player is authenticated.")
NSLog("My name is \(localPlayer.playerID)")
} else {
NSLog("Not authenticated")
NSLog("Player is \(localPlayer.playerID)")
}
}
} else {
NSLog("Player is already authenticated!")
}
}
and here is my code to detect nearby devices in a separate UIViewController:
override func viewDidLoad() {
devicesLabel.text = "Waiting for devices..."
searchForDevices()
NSLog("Ran searchForDevices()")
}
private func searchForDevices() {
GKMatchmaker.sharedMatchmaker().startBrowsingForNearbyPlayersWithHandler() {
var status = $1 ? "true" : "false"
self.devicesLabel.text = "Reachability changed for player \($0) with status: \(status)"
}
}
No matter what I do with my two iPads (both are model iPad 3), neither one ever sees the other. Am I calling startBrowsingForNearbyPlayersWithHandler correctly?
Also notice that in the authorization code above, I'm using the Objective-C workaround recommended by this post: Game Center not authenticating using Swift, since the "Swift way" of doing that didn't work for me either.
I also ran Spelltower across both devices over local WiFi, so it looks like the hardware is functioning properly. Any idea what could be going wrong here?
I decided to abandon developing this through Game Center and to use Multipeer Connectivity instead.
You are not registering a class to receive invitation updates. You need to register a class and implement methods conforming to the protocol for GKLocalPlayerListener. See my response in this post (it is in Objective-C, but the same concept applies):
Some startBrowsingForNearbyPlayersWithReachableHandler questions

Resources