Background: While users are on the go, the data source often switches towers or downgrade/upgrade between 2G/3G/WiFi. The phone app can also go in to the background if the user locks the screen or presses the home button. This has an impact on applications/games that rely on persistent data connectivity. AppWarp also provides a powerful connection resiliency feature for gracefully handling such cases by maintaining the user’s room and subscriptions on the server during such intermittent issues.
Implement connection resiliency feature
I have developed Catapult War sample game which was described in the previous post. In this game, I am going to handle connection error and synchronize games parameter during this time.
To enable connection resiliency in windows game, you need to set the Recovery Allowance interval after initializing WarpClient. Recommended values are between 60 to 120 i.e. 1 minute to 2 minutes. By default recovery allowance time is 0, but if we have set the recovery allowance time then Appwarp server will maintain the user’s session and wait for the user to recover his connection for that amount of time. If user successfully recovers his connection then within that time his game will be resumed at the same state where he had lost the connection.
public JoinPage()
{
InitializeComponent();
// Initialize the SDK with your applications credentials that you received
// after creating the app from http://apphq.shephertz.com
WarpClient.initialize(GlobalContext.API_KEY, GlobalContext.SECRET_KEY);
WarpClient.setRecoveryAllowance(60);
// Keep a reference of the SDK singleton handy for later use.
GlobalContext.warpClient = WarpClient.GetInstance();
}
Connection Breaks
We get connection state responses in “onConnectDone” method of ConnectionRequestListener. When connection breaks at my end, I get the response code WarpResponseResultCode.CONNECTION_ERROR_RECOVERABLE.In Catapult war, I am trying to recover the connection on every 10 seconds. Since I have set the recovery allowance 60 seconds therefore, I will try it max 6 times. After 6 tries if I am unable to recover the connection then I will bring the user out from the game.
public void onConnectDone(ConnectEvent eventObj) {
switch (eventObj.getResult()) {
case WarpResponseResultCode.SUCCESS:
GlobalContext.IsConnectedToAppWarp = true;
_recoverCounts = 0;
// Successfully connected to the server. Lets go ahead and init the udp.
//Init udp is essentional if we are using UDP communication in our Game
WarpClient.GetInstance().initUDP();
if (mOnConnectDoneCallback != null) { //Request Was From Main Screen
Deployment.Current.Dispatcher.BeginInvoke(new ConnectionCallback(mOnConnectDoneCallback));
} else if ((mOnConnectDoneCallback == null) && mShowResultCallback != null) {
//Request Was From Join Screen
Deployment.Current.Dispatcher.BeginInvoke(new ShowResultCallback(mShowResultCallback), "connected");
}
break;
case WarpResponseResultCode.CONNECTION_ERROR_RECOVERABLE:
Deployment.Current.Dispatcher.BeginInvoke(delegate() {
RecoverConnection();
}
);
if (mConnectionRecoverableError != null) {
Deployment.Current.Dispatcher.BeginInvoke(new ConnectionCallback(mConnectionRecoverableError));
}
break;
case WarpResponseResultCode.SUCCESS_RECOVERED:
Deployment.Current.Dispatcher.BeginInvoke(delegate() {
ConnectionRecovered();
}
);
if (mConnectionRecoverd != null) {
Deployment.Current.Dispatcher.BeginInvoke(new ConnectionCallback(mConnectionRecoverd));
}
break;
default:
GlobalContext.IsConnectedToAppWarp = false;
if (mShowResultCallback != null) {
Deployment.Current.Dispatcher.BeginInvoke(new ShowResultCallback(mShowResultCallback), "connection failed");
}
break;
}
}
public void RecoverConnection()
{
if (_recoverCounts == 0) {
timer = new DispatcherTimer();
//Timer for Connection Recover:trying to reconnect in every 10 second,Since i have set recovery allowance to 60 seconds so
//it will try for 6 times i.e _recoverCounts<=6
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(0, 0, 0, 10);
timer.Start();
}
}
public void ConnectionRecovered()
{
timer.Stop();
_recoverCounts = 0;
}
private void timer_Tick(object sender, EventArgs e)
{
_recoverCounts++;
if (_recoverCounts <= 6) {
WarpClient.GetInstance().RecoverConnection();
} else {
(sender as DispatcherTimer).Stop();
GlobalContext.IsConnectedToAppWarp = false;
if (mShowResultCallback != null) {
Deployment.Current.Dispatcher.BeginInvoke(new ShowResultCallback(mShowResultCallback), "connection failed");
}
}
}
If Connection is recovered successfully, we will get the WarpResponseResultCode as SUCCESS_RECOVERED.
At remote user
During the time user is trying to recover his connection, Appwarp server tells to remote user that your opponent has been paused, at remote user onUserPaused event gets Invoked. In Catapult war the game at remote user’s end is paused too, and we wait for opponent to get resumed. With this practice we can keep our game parameters synchronized.
public void onUserPaused(string locid, bool isLobby, string username)
{
if (!GlobalContext.localUsername.Equals(username) && !isLobby) {
if (RemoteUserPaused != null) {
Deployment.Current.Dispatcher.BeginInvoke(new UserPaused(RemoteUserPaused));
}
}
}
When opponent successfully recovers his connection, onUserResumed gets invoked at remote user.
public void onUserResumed(string locid, bool isLobby, string username)
{
if (!GlobalContext.localUsername.Equals(username) && !isLobby)
{
if (RemoteUserResumed != null) {
Deployment.Current.Dispatcher.BeginInvoke(new UserResumed(RemoteUserResumed));
}
}
}
But if opponent fails to recover his connection then at remote user end onUserLeftRoom event will be invoked. In Catapult War I have brought the user to menu screen so that he can start a new game.
public void onUserLeftRoom(RoomData eventObj, String username)
{
if (eventObj.getId().Equals(GlobalContext.GameRoomId)) {
if (!GlobalContext.localUsername.Equals(username)) {
if (OpponentLeftRoom != null) {
Deployment.Current.Dispatcher.BeginInvoke(new UserLeftRoom(OpponentLeftRoom));
}
}
}
}
Source Code can be downloaded or viewed from our Git repo. If you have any questions or need any further assistance, please feel free to write us at support@shephertz.com.
Leave A Reply