package com.fiteclub.android.smack; import org.json.JSONException; import org.json.JSONObject; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MatchService extends Service { private static final String TAG = "MatchService"; public static final String ACTION_MATCH_SERVICE = "com.fiteclub.match.ALL"; public static final String EXTRA_MATCH_ERROR_MSG = "com.fiteclub.match.errmsg"; public static final String EXTRA_GAME_START = "com.fiteclub.game.start"; public static final String EXTRA_GAME_ROOMNAME = "com.fiteclub.game.roomname"; public static final String EXTRA_GAME_PLAYER1 = "com.fiteclub.game.player1"; public static final String EXTRA_GAME_PLAYER2 = "com.fiteclub.game.player2"; public static final int PLAYER1_SIDE = 1; public static final int PLAYER2_SIDE = 2; private XmppManager xmppManager; private int state = 0; private String userName; private int broadcastSeconds; private int listenSeconds; private String gameRoomName; private String sendJsonText; private int maxSendCount; private int sendCount; private int sendTick; @Override public void onCreate() { super.onCreate(); xmppManager = XmppManager.getManager(); } @Override public IBinder onBind(Intent intent) { return null; } private void broadcastErrorMsg(String msg) { Log.d(TAG, "broadcastErrorMsg state=" + state); Intent intent = new Intent(); intent.setAction(ACTION_MATCH_SERVICE); intent.putExtra(EXTRA_MATCH_ERROR_MSG, msg); this.sendBroadcast(intent); } private void broadcastStartGame(int side, String player1, String player2, String roomName) { Log.d(TAG, "broadcastStartGame state=" + state); //player1 = "fiteclub.muthu@gmail.com"; //player2 = "fiteclub.tu@gmail.com"; Intent intent = new Intent(); intent.setAction(ACTION_MATCH_SERVICE); intent.putExtra(EXTRA_GAME_START, side); intent.putExtra(EXTRA_GAME_ROOMNAME, roomName); intent.putExtra(EXTRA_GAME_PLAYER1, player1); intent.putExtra(EXTRA_GAME_PLAYER2, player2); this.sendBroadcast(intent); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); Log.d(TAG, "onStart state=" + state); if (state != 0) { broadcastErrorMsg("match service is busy!"); return; } state = 1; //connecting match room new Thread(new Runnable() { public void run() { doMatch(); state = 0; //back to init } }).start(); } private void doMatch() { Log.d(TAG, "doMatch state=" + state); if (!startMatch()) return; int tick1 = listenSeconds * 1000; int tick2 = (listenSeconds + broadcastSeconds) * 1000; int tick = 0; sendCount = 0; sendJsonText = null; sendTick = 0; while (tick < tick2) { switch (state) { case 2: //listening game request if (tick > tick1) state = 3; break; case 3: //broadcast game request if (tick > sendTick) { if (sendJsonText == null) sendJsonText = MessageUtil.createWatingFightMessage(userName, gameRoomName); sendMessageToChatRoom(); sendTick = tick + 2000; } break; case 5: //accept the game if (tick > sendTick) { if (sendCount > 0) { sendMessageToChatRoom(); sendCount--; sendTick = tick + 2000; } else { sendJsonText = null; if (tick > tick1) { state = 3; } else { state = 2; } } } break; case 6: //start the game as player 1 if (tick > sendTick) { if (sendCount > 0) { sendMessageToChatRoom(); sendCount--; sendTick = tick + 2000; } else { sendJsonText = null; state = 7; } } break; case 7: //done case 8: //start the game as player 2 Log.d(TAG, "doMatch finishing start game state=" + state); xmppManager.leaveMatchRoom(); return; default: broadcastErrorMsg("Interal state error!"); return; } String message = xmppManager.getNextMatchMessage(); if (message != null) { processMessage(message); continue; } tick += 300; } if (state == 3) { state = 4; //time out xmppManager.leaveMatchRoom(); broadcastErrorMsg("can not match a player!"); } } private void sendMessageToChatRoom() { Log.d(TAG, "sendMessageToChatRoom state=" + state); Log.d(TAG, "sendMessageToChatRoom message=" + sendJsonText); if (sendJsonText == null) return; xmppManager.sendMatchMessage(sendJsonText); } private void processMessage(String message) { try { JSONObject json = new JSONObject(message); Log.d(TAG, "processMessage state=" + state); Log.d(TAG, "processMessage message=" + json.toString()); int msgType = MessageUtil.getMessageType(json); switch (msgType) { case MessageUtil.MSG_TYPE_WAITING_GAME: acceptGame(json); break; case MessageUtil.MSG_TYPE_ACCEPT_GAME: startGameAsPlayer1(json); break; case MessageUtil.MSG_TYPE_START_GAME: startGameAsPlayer2(json); break; } } catch (JSONException e) { e.printStackTrace(); } } private void startGameAsPlayer2(JSONObject json) { Log.d(TAG, "startGameAsPlayer2 state=" + state); if (state != 5) //only process the packet when in "accept the game" state return; String player2 = MessageUtil.getPlayer2(json); if (!userName.equals(player2)) return; String player1 = MessageUtil.getUserName(json); String roomName = MessageUtil.getGameRoomName(json); broadcastStartGame(PLAYER2_SIDE, player1, player2, roomName); state = 8; //start the game as player 2 } private void startGameAsPlayer1(JSONObject json) { Log.d(TAG, "startGameAsPlayer1 state=" + state); if (state != 3) //only process the packet when in "broadcast request" state return; String player1 = MessageUtil.getUserName(json); if (!userName.equals(player1)) return; String roomName = MessageUtil.getGameRoomName(json); if (!gameRoomName.equals(roomName)) return; String player2 = MessageUtil.getPlayer2(json); sendJsonText = MessageUtil.createStartFightMessage(player1, player2, roomName); state = 6; //start the game as player 1 sendCount = maxSendCount; sendTick = 0; broadcastStartGame(PLAYER1_SIDE, userName, player2, roomName); } private void acceptGame(JSONObject json) { Log.d(TAG, "acceptGame state=" + state); if (state != 2) //only process the packet when in "listen" state return; String player1 = MessageUtil.getUserName(json); if (player1 == null) return; String roomName = MessageUtil.getGameRoomName(json); sendJsonText = MessageUtil.createAcceptFightMessage(userName, player1, roomName); state = 5; //accept the game sendCount = maxSendCount; sendTick = 0; } private boolean startMatch() { if (!xmppManager.checkConnection()) { broadcastErrorMsg("Can not connect to xmpp server!"); return false; } if (!xmppManager.checkLogin()) { broadcastErrorMsg("can not login the xmpp server!"); return false; } if (!xmppManager.checkMatchRoom()) { broadcastErrorMsg("can not join the match room!"); return false; } userName = xmppManager.getUserName(); gameRoomName = xmppManager.getPlanRoomName(); broadcastSeconds = 50; listenSeconds = 10; maxSendCount = 5; state = 2; //listening game request return true; } @Override public void onDestroy() { super.onDestroy(); xmppManager.clear(); } }