Invite players programmatically into a match

I am using Swift 4.


I am able to authenticate the localplayer and find a match using the Game Center match viewcontroller. I was also able to link the iOS simulator (player1) to my real iPhone 8 device (player2) into a match for test purposes.


However, after the localplayer is authenticated, I would like to obtain a list of all my game center "friends" myself and then create my own viewController interface to invite/connect players into the game. I was able to call "GKLocalPlayer.local.loadChallengableFriends( )" to obtain the friends, but I am not sure how to properly invite them to a match one by one programmatically.


Googling indicates GKMatchmaker inviteHandler, GKInvite and "player DidAccept" are involved but I do not know how to put this all together.


Any pointers, hints or sample code would be greatly appreciated.


In the meantime, I will continue to Google around

Accepted Reply

ok, thanks for your input. I really want to create my own viewcontroller so my interface looks like it is part of my game motif instead of some default Game CEnter interface. However, we will see how it goes 🙂 . There is not a lot of examples using swift 4 so I am trying to read everything and put the pieces of the puzzle together bit by bit.

Replies

Hello everyone. I am new to this forum. Interesting thread 😮

From the documentation:


"If the value of [GKMatchRequest.recipients] is non-

nil
, when you use the request to create a match, Game Center invites those players to the match. No automatching is done and the
GKMatchRequest
maxPlayers
and
minPlayers
properties are ignored."

Hey PBK,


Not sure about the uncletr but how Go Game Connect does it in regards to multiplayer is also more ore less what I was hoping to do. Seems all I have to do is initalize the GKMatchmakerViewController with the match?


But.. ideally I would skip directly to the controller that is shown when the player taps the "Invite" button. Is that possible? Should be..

Hi, Did you end up having any luck with this? I'm having the same issue with implementing the invitation handler...which has a bunch of deprecated items associated with it in the documentation.


https://developer.apple.com/documentation/gamekit/gkmatchmaker/1521060-invitehandler


var inviteHandler: ((GKInvite, [Any]?) -> Void)? { get set }


I just want to know how to actually accept an invite? I can send one, and on the test device have a notification banner that launches the app...but what do we do from there?

Did you look into the GKLocalPlayerListener?


The critical step is to register your GameKit wrapper (the entity you have setup to receive the invite related push events) to make it receive the local player related events - including those relevant for invites:


GKLocalPlayer.local.register(self)


Then the handler will receive all these events - which are all part of the GKLocalPlayerListener:


    // MARK: GKInviteEventListener
    
    func player(_ player: GKPlayer, didAccept invite: GKInvite) {
        print("Did accept invite, update UI or show and start the game?")
    }
    
    func player(_ player: GKPlayer, didRequestMatchWithRecipients recipientPlayers: [GKPlayer]) {
        print("Did request match with recipients")
    }
    
    func player(_ player: GKPlayer, didRequestMatchWithPlayers playerIDsToInvite: [String]) {
        print("Did request match with players")
    }


Hope this helps.

Thanks for the reply!!


Yes, I'm using the GKLocalPlayerListener protocol. I'm at the point where I can receive the invite, have it launch the app and I can even accept the invite it on the test device, and get it to call 'did accept invite'. That's great, but it then gets stuck on the matchmaker, and never calls 'did find match'. What am I missing?

Here's what I do from there: (I do not recall why I had to check for 'didAcceptInviteVCShowing' and dismiss it if it was showing.)




-(void)acceptThisInvite:(GKInvite *)invite{
    didAcceptInviteVCShowing=YES;
    GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:invite];
    mmvc.matchmakerDelegate = self;
    [[self topController] presentViewController:mmvc animated:YES completion:^{
        if (@available(iOS 11.0, *)) {
            mmvc.view.frame=CGRectMake(0,mmvc.view.safeAreaInsets.top, mmvc.view.bounds.size.width, mmvc.view.bounds.size.height-mmvc.view.safeAreaInsets.top);
        } else {
            // Fallback on earlier versions
        }    
    }];
}

- (void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite{
    
    if(!didAcceptInviteVCShowing){
       [self acceptThisInvite:invite];
    }else{
        [[self topController] dismissViewControllerAnimated:YES completion:^{
            [self acceptThisInvite:invite];
        }];
    }
}
   

Thank you so much for your help! I'm still struggling though.


How would I write this example in Swift? What are we trying to do here? If the VC is showing, accept the invite?? There isn't an "acceptThisInvite" function...


How do I accept an invite? This is the piece I'm missing. I'm able to get the app to call "didAcceptInvite", but it never gets to "didFindMatch", which is what starts the game. There must be a step in between...


I'm sure Game Center must provide a way to do this?


Thank you again,


Dan

Sorry, I don't do Swift.


In didAcceptInvite you first check to see if you are already displaying a "did accept invite" MatchMaker view controller (didAcceptInviteVCShowing=YES). If you are, you dismiss it and then show the new view controller only after it is dismissed. But if you are not showing the "did accept invite" view controller then you immediately show a "did accept invite" "mmvc" viewController. The mmvc delegate will call didFindMatch: when it is dismissed by the user. In didFindMatch you set didAcceptInviteVCShowing back to NO.



I created the method acceptThisInvite because it is called in two places. Perhaps this will be simplier to translate into Swift:


- (void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite{
      
    if(!didAcceptInviteVCShowing){
        didAcceptInviteVCShowing=YES;
        GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:invite];
        mmvc.matchmakerDelegate = self;
        [[self topController] presentViewController:mmvc animated:YES completion:^{
            if (@available(iOS 11.0, *)) {
                mmvc.view.frame=CGRectMake(0,mmvc.view.safeAreaInsets.top, mmvc.view.bounds.size.width, mmvc.view.bounds.size.height-mmvc.view.safeAreaInsets.top);
            } else {
                // Fallback on earlier versions
            }
        }];
    }else{
        [[self topController] dismissViewControllerAnimated:YES completion:^{
            didAcceptInviteVCShowing=YES;
            GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:invite];
            mmvc.matchmakerDelegate = self;
            [[self topController] presentViewController:mmvc animated:YES completion:^{
                if (@available(iOS 11.0, *)) {
                    mmvc.view.frame=CGRectMake(0,mmvc.view.safeAreaInsets.top, mmvc.view.bounds.size.width, mmvc.view.bounds.size.height-mmvc.view.safeAreaInsets.top);
                } else {
                    // Fallback on earlier versions
                }
            }];
        }];
    }
}

apple App Store