Search code examples
iosobjective-cgame-centergamekit

Data gets messed up when sent between two devices


I built a multiplayer game which works perfectly on my iPhone 5s played against the simulator. But whenever I try to play from my 5s against an iPhone 5, there are some problems.

The game sends two values to the other player: score and level.

In case the iPhone 5s sends the values: iPhone 5 thinks score = 0 and level = the value we sent as the score.

typedef struct {
    NSUInteger score;
    NSUInteger level;
} MessageNewScore;

- (void)sendData:(NSData *)data {
    NSError *error;
    GameKitHelper *gameKitHelper = [GameKitHelper sharedGameKitHelper];

    BOOL success = [gameKitHelper.match sendDataToAllPlayers:data withDataMode:GKMatchSendDataReliable error:&error];
    if (!success) {
        NSLog(@"Error sending data:%@", error.localizedDescription);
    }
}

// Run on iPhone 5s
- (void)sendNewScore:(NSUInteger)score level:(NSUInteger)level{
    NSLog(@"score: %lu", (unsigned long)score); // E.g. 1930
    NSLog(@"level: %lu", (unsigned long)level); // E.g. 7

    MessageNewScore messageNewScore;
    messageNewScore.message.messageType = kMessageTypeNewScore;
    messageNewScore.score = score;
    messageNewScore.level = level;
    NSData *data = [NSData dataWithBytes:&messageNewScore
                              length:sizeof(MessageNewScore)];

    [self sendData:data];

    NSLog(@"score: %lu", (unsigned long)messageNewScore.score); // 1930
    NSLog(@"level: %lu", (unsigned long)messageNewScore.level); // 7
}

// Run on iPhone 5
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
    MessageNewScore *messageNewScore = (MessageNewScore*)[data bytes];

    NSLog(@"score: %lu", (unsigned long)messageNewScore->score); // According to iPhone 5 this is 0
    NSLog(@"level: %lu", (unsigned long)messageNewScore->level); // According to iPhone 5 this is 1930

    [_delegate enemysScoreReceived:messageNewScore->score level:messageNewScore->level];
}

In the last case, the values from logging in sendNewScore:: are correct and in didReceiveData:: are wrong. I figured this could have something to do with the 64-bit processor in the 5s, but not sure how to fix this.


Solution

  • The iPhone 5 uses uses an Apple A6 (32-bit), the iPhone 5S an Apple A7 (64-bit) processor.

    You need to encode/decode NSData that is sent between players in a portable representation, such as can be obtained with NSKeyedArchiver/NSKeyedUnarchiver for encoding/decoding NSIntegers, etc. You are currently sending structs whose representation is processor-specific.