Search code examples
iphonegamekitgksession

Connect 3rd Device using GameKit


I am using GameKit on a basic level right now. I am able to connect two devices and send messages between them.

I have 3 devices, we'll call them device A, B and C.

I am able to connect A to B, A to C, and B to C, as individual setups.

If I connect A to B, then attempt to connect B to C, Device C will show that Device B is available, but device B continues to spin and say "Looking for available iPod, iPhones..."

In peerPickerController:sessionForConnectionType: , when I am attempting to connect B to C, I am trying to have device B reuse its same GKSession that it is using in its connection to A... because if I create a new session on device B, it is able to connect to Device C but drops the connection to device A.

Here is the sessionForConnectionType :

 -(GKSession*)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type {

   // session is a synthesized GKSession
        if (session == nil) {
            session = [[GKSession alloc] initWithSessionID:nil  displayName:@"" sessionMode:GKSessionModePeer];
            session.delegate = self;        
        } 


        return session;
    }

Solution

  • I ended up going with a Server / Client setup, which is easier to manage. This way, there is only one Server PeerID, as opposed to a Server PeerID for every connection. I wasn't able to find many good examples, so I've included the basic GameKit Server / Client code here.

    // if the device in an ipad, treat it as a host / server
    if ([[[UIDevice currentDevice] model] isEqualToString:@"iPad"]) {
            isHost = YES;
        } else {
            isHost = NO;
        }
    
    // monitor if this device is connected to another device
        isConnected = NO;
    }
    
    
    
    
    #pragma mark GameKit Methods
    
    // Called when a change in the connection state is detected
    - (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
    
        NSLog(@"Session:Peer:%@ Did Change State", peerID);
         Globals *globals = [Globals shareData];
    
        switch (state) {
            case GKPeerStateConnected:
                NSLog(@"GKPeerStateConnected");
    
                [globals.localSession setDataReceiveHandler:self withContext:nil];
    
    // if this device is not the host and is not connected yet...
                if (!isHost && !isConnected) {
    
    // update variables, save the Server PeerId and the local Session so we can use them later 
                    isConnected = YES;
                    serverSession = peerID];
                    localSession = session;
                }
                break;
    
            case GKPeerStateDisconnected:
                NSLog(@"GKPeerStateDisconnected");
                break;
    
            case GKPeerStateAvailable:
                NSLog(@"GKPeerStateAvailable");
                if (!isHost) {
                    NSLog(@"Attempting to Connect...");
    // the server is available, try to connect to it
                    [session connectToPeer:peerID withTimeout:20];
                }
                break;
    
            case GKPeerStateConnecting:
                NSLog(@"GKPeerStateConnecting");
                break;
    
            case GKPeerStateUnavailable:
                NSLog(@"GKPeerStateUnavailable");
                break;
        }
    
    }
    
    // Called if this device receives a request for a connection
    // This should only happen on the Server device
    -(void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID {
        NSLog(@"Received Connection Request From %@", peerID);
    
    // Accept the connection request from the peer
        [session acceptConnectionFromPeer:peerID error:nil];
    }
    
    - (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context {
        NSLog(@"Received Data");   
    }
    
    -(void)session:(GKSession *)session didFailWithError:(NSError *)error {
        NSLog(@"Session Failed: %@", error);
    }
    
    
    // Connected to a UIButton
    -(IBAction)sendData {
        NSLog(@"Sending Data ...");   
    }
    
    // Connected to a UIButton
    -(IBAction)beginConnection {
    
        Globals *globals = [Globals shareData];
    
    // Set this up as a server
        if (isHost) {
            GKSession *session = [[GKSession alloc] initWithSessionID:@"" displayName:@"Server" sessionMode:GKSessionModeServer];
            session.delegate = self;
            session.available = YES;       
            NSLog(@"Setting Server Session Peer:%@",  session.peerID);
            globals.localSession = session;
        } 
    
    // or set it up as a client
    else {
            GKSession *session = [[GKSession alloc] initWithSessionID:@"" displayName:nil sessionMode:GKSessionModeClient];
            session.delegate = self;
            session.available = YES;
            NSLog(@"Setting CLIENT Session Peer:%@", session.peerID);
            globals.localSession = session;
        }
    
    }
    
    
    ... Dealloc, etc...
    
    @end