GKTurnBasedMatch - player( receivedExchangeReplies ) not triggered for CurrentParticipant

60 Views Asked by At

so Ive been at this for weeks now and never found an answer anywhere in the net. The sourcecode comments, various documentations and various sources claim the function ReceivedExchangeReplies(GKPlayer, GKTurnBasedExchangeReply[], GKTurnBasedExchange, GKTurnBasedMatch) is supposed to be called when all Recipients of the exchange either reply or timeout. It is supposed to be called for both the initiator of the exchange and the currentParticipant.

But in my App it only ever gets called for the initiator of the exchange, not the turnholder. I'm unable to proceed with my coding, since the current turnholder is supposed to merge and resolve the exchanges once they are done. But it cannot do so, since it never gets notified about the exchange becoming completed.

AuthenticationHandler works normal and is to no concern to the problem:

func authenticateLocalPlayer() {
    let localPlayer: GKLocalPlayer = GKLocalPlayer.localPlayer()
    localPlayer.authenticateHandler = {(ViewController, error) -> Void in
        if((ViewController) != nil) {
            self.underlyingViewController.present(ViewController!, animated: true, completion: nil)
        } else if (localPlayer.isAuthenticated) {
            self.gamecenterEnabled = true
            localPlayer.unregisterAllListeners()
            localPlayer.register(self)
            self.findBattleMatch()
        } else {
            self.gamecenterEnabled = false
            print(error as Any)
        }
    }
}

Here is how the Exchange Request is sent:

currentMatch.sendExchange(to: [nextParticipant], data: GameState.encodeStruct(structToEncode: structToSend), localizableMessageKey: messageKey, arguments: ["X","Y"], timeout: TimeInterval(timeOutDebug), completionHandler: {(exchangeReq: GKTurnBasedExchange?,error: Error?) -> Void in
    if(error == nil ) {
        print("Operation successfull")
    } else {
        print(error as Any)
    }
})

Being replied with Reply:

exchange.reply(withLocalizableMessageKey: exchange.message! , arguments: ["XY","Y"], data: GameState.encodeStruct(structToEncode: exchangeReply), completionHandler: {(error: Error?) -> Void in
    if(error == nil ) {
        print("ExchangeReply sent successfully")
    } else {
        print(error as Any)
    }
})

After that on completion of the exchange, the following overriden function should be called automatically. For both, for the initiator of the exchange and for the current turnholder:

func player(_ player: GKPlayer, receivedExchangeReplies replies: [GKTurnBasedExchangeReply], forCompletedExchange exchange: GKTurnBasedExchange, for match: GKTurnBasedMatch){
    print("Exchange was completed, turnholder and Exchange-initiator should act on that in following code.")
    ...code...
}

This is the Swift-version of the above mentioned ObjectiveC function.

Now the problem like said is, that the above function is being called only for the inititor of the exchange, while it not being called for the current turnholder (like it is supposed to be). The current turnholder is supposer to merge the changes made by exchanges into the savegame data. Him not being notified like he should leaves an issue and a problem, because he cannot act without being notified. I could implement him being notified manually by another additional exchange (which is the workaround I'm currenly using), but that is somehow beside the point, since he would have to merge the new exchange blindly without any certainty about it being completed.

The first 3 steps are working just fine it seems, since I see the initiator of the exchange being notified. Only problem is the fourth function not being automatically called like described in Documentations and tutorials.

One of my latest interpretations was that the exchange gets completed too fast without the listener ever realizing it was ever active (the exchange is replied to immediately on receival); but that is just a wild guess. Even if I wanted to... whatever I do to delay replying to the exchange (for example saving a reference on the exchange, using DispatchQueue for a delayed function call or similar) results in either the exchange turning out nil or communication errors (message was sent over different proxy error).

Basically I wonder if the turnholder is really supposed to get notified by the above function being called or if it might have been changed.

I would really appreciate help here, Ive been at this for weeks and havent gotten anywhere. Everything else is working fine. Im using the latest version of Swift with the most recent approach of utilizing GKLocalPlayer instead of implementing the Listener directly (like it is recommended everywhere).

kindly regards, Skeltek

0

There are 0 best solutions below