Sign In Register

How can we help you today?

Start a new topic
Answered

Passing the turn back and forth on a noisy network

Network errors were my bane writing an asynchronous turn-based game with iOS Game Center, so I wonder how GameSparks will make my life easier (for another iOS async turn-based game).


My vague understanding is that I would post a turn using LogChallengeEventRequest. There are basically two errors I dealt with in the past:


1. The turn could not reach the server

2. The server got the turn but could not notify the client before the client timed out waiting for a reply


#2 is a false negative, but in the short run we don't know that.


#1 is handled simply by retrying. Of course, being mobile, you might have to try hours later, when you are no longer on the airplane. Is there any way to do this automatically? (Since if I have to save the commands, it's probably going to look almost identical to what you send as JSON.)


#2 is potentially a problem. If I send again, the data may have been updated by the other player. I need to make sure not to overwrite it. I can of course query the server before retrying, but there's still a potential race condition between the two devices.


How am I supposed to handle an atomic turn pass and prevent a race updating the game state?


Best Answer

OK, I follow.


We can probably do something around this using the requestId generated by unity, and not process it if we've already seen it for the current player.


We'll get something into next weeks sprint for this. I'm thinking a boolean flag against event : "Reject Duplicate RequestId's for players".


Does that sound correct for you?


Gabriel


Hi David


If you set your challenge up as a turn based challenge the only the current player can send  LogChallengeEventRequest to that challenge at any time. GameSparks will manage who's turn it is and will not allow you to play out of turn. If your request is not sent, it will remain your turn until it is sent.


The Android SDK has a sendEventually method that caches the request if it's not sent, and will retry when the device is back online. This functionality is due to be added to the Unity SDK shortly.


What SDK are you using?


Gabriel

We'd be using Unity. (And our game needs to be client-driven.)


So it sounds like the server does help, but there's still the problem of false negatives. They happen when the turn is sent, but the client does not realize it.


Here's the situation, with two players (p1 and p2).

p1 sends state (A) but is told there's an error because the connection dropped the instant the server got the data, and there is no possible acknowledgement. But the server got the data, so it's p2's turn.

p2 receives A, makes a move, and sends the new state (B) to the server.

Moments later, p1 manages to send the queued state. This (A) overwrites the later move (B), because the server knows that it is p1's turn.

Answer

OK, I follow.


We can probably do something around this using the requestId generated by unity, and not process it if we've already seen it for the current player.


We'll get something into next weeks sprint for this. I'm thinking a boolean flag against event : "Reject Duplicate RequestId's for players".


Does that sound correct for you?


Gabriel

I think that's what we need.


I also think it's pretty much something only you can do, since without sendEventually functionality, our code would have to detect the error (whether false or legitimate) and generate a new request later.

Login to post a comment