Showing posts with label Netty. Show all posts
Showing posts with label Netty. Show all posts

Sunday, January 24, 2016

Multiplayer Card Game using WebSockets,Java Netty Server ,Cocos2d-x-HTML5 - Part 5

Game Server Source code overview



Now we are close to the point which we return with WebSocket response the new game states to the clients , but what are those "Game states" ?
it can be represented in many ways but in our case which is super simple the states will be kepet
in 2 levels .

First level is global game state and all things that are relevant to the general game like:
How many players are in the game
What is the scoring status
Who is the winner
How many cards left in the middle card deck

Second level of states are the ones that relevant to the players
Each player has several states , the states are updated during the game .


Player.java

This is the class that represent the player and the player states
Only the important code is explained all the rest of the code are getters and setter to the members
of The Player Class.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Player {
 private final static Logger LOG = LoggerManager.GetLogger(GameServerMain.class.getName());
 private LinkedList<String> PlayerCards;
 private String userName;
 private int Event;
 //Session channel
 private Channel channel;
 //Player Json massage
 private String playerJson;
 //the player which is active and has the turn
 private int activeplayerid;
 private int id;
 private String activecardid;
 private int registertionNum;
 private int winner;
 private String winnercards;
 private String deckcard;
 //mark the end game the value will be the winner id
 private int endgame;
  public Player()
 {
  this.channel = null;
  Init();
 } 
 public Player(Channel _channel)
 {
  this.channel = _channel;
  Init(); 
 }



  1. Line 3 : the cards that were dealt to the player , which are the half of the total cards in the page
  2. Line 4 : player user name.
  3. Line 5 : player event , the current event that the player is in.
  4. Line 7 : each player will hold the Netty channel in which it used to communicate from the client . this channel will be used to inform back to the client the state of the palyers and the state of the game.
  5. Line 9 : the json string that is constructed during the process of playing the game in the server , this json will be the one that used to send back to the player client .
  6. Line 11 : the id of the player that is currently active , that means the one that is playing its turn
  7. Line 12 : player unique id.
  8. Line 13 : the card that is played now 
  9. Line 14 : the order of which the player registered , this way it will be determined the player turn. 
  10. Line 15 : mark as winner of this game
  11. Line 16 : save the winner cards in this global game turn the format is:
    currentPlayerCardId+"_"+ prevCardId
  12. Line 17 : the card which is now on the middle card deck.
  13. Line 19 : Id of the player that win the game
  14. Lines 25 - 29 : Player Constructure that gets the player channel instance
    This channel instance will be used to communicate with the client .
GameResponseDispatcher.java
This class is responsible to build the JSON object that will be send back to the clients that are associated with this game .
The class have 2 main response functions as you remember we have 2 main events in the game
LOGIN and PLAY.
so the class will handle the response to the LOGIN event  :ResponseDispatcheLoginDone
and to the PLAY event : 
ResponseDispatchePlayDone


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
public class GameResponseDispatcher {
 private final static Logger LOG = LoggerManager.GetLogger(GameEventHandler.class.getName());
 private GameManager gameManager; 
 
 public GameResponseDispatcher(GameManager _gameManager)
 {
  this.gameManager = _gameManager;
   
 }
 public boolean ResponseDispatcheLoginDone(int  _playerId)
 {
  int currentPlayerId = _playerId;
  Player currentPlayer = this.gameManager.getPlayers().get(currentPlayerId);
  
  JSONObject currentPlayerJsonObj = setPlayerToJson(currentPlayer,
               currentPlayer.getEvent(),
               currentPlayer.getId());
  
  JSONObject currentPlayerJsonObj2 = setPlayerToJson(currentPlayer,
              currentPlayer.getEvent(),
              currentPlayer.getId());
   
  //build the other players json
     JSONArray currentPlayerArrayNewPlayers = new JSONArray();
     JSONArray ArrayCurrentPlayers = new JSONArray();
     ArrayCurrentPlayers.put(currentPlayerJsonObj2);
     Iterator<Entry<Integer, Player>> it = this.gameManager.getPlayers().entrySet().iterator();
     while (it.hasNext()) {
      @SuppressWarnings("rawtypes")
   Map.Entry pair = (Map.Entry)it.next();
         Player playerIt = ((Player)pair.getValue());
          
         if(currentPlayerId != playerIt.getId())
         {
          this.gameManager.getPlayers().get(playerIt.getId()).setEvent(Config.NEW_USER_LOGIN_DONE); 
          JSONObject playerJsonObjIt = setPlayerToJson(playerIt,
                     Config.NEW_USER_LOGIN_DONE,
                     playerIt.getId());
          JSONObject newPlayerForCurrent  = setPlayerToJson(playerIt,
                      Config.NEW_USER_LOGIN_DONE,
                      playerIt.getId());
          //to current    
          currentPlayerArrayNewPlayers.put(newPlayerForCurrent);
          //to others 
          playerJsonObjIt.put("players",ArrayCurrentPlayers);
          String jsonStr = playerJsonObjIt.toString();
          this.gameManager.getPlayers().get(playerIt.getId()).setPlayerJson(jsonStr);
         }
     }
     //current user array
     currentPlayerJsonObj.put("players",currentPlayerArrayNewPlayers);
     String jsonStr = currentPlayerJsonObj.toString();
     this.gameManager.getPlayers().get(currentPlayerId).setPlayerJson(jsonStr);
    return true;
 }
 
 public boolean ResponseDispatchePlayDone(int _playerId)
 {
  int currentPlayerId = _playerId;
  this.gameManager.getPlayers().get(currentPlayerId).setEvent(Config.PLAY_DONE);
  int newActivePlayer = this.gameManager.getNextActivePlayer(currentPlayerId);
  this.gameManager.getPlayers().get(currentPlayerId).setActiveplayerid(newActivePlayer);
  
  Player currentPlayer = this.gameManager.getPlayers().get(currentPlayerId);
  
  JSONObject currentPlayerJsonObj = setPlayerToJson(currentPlayer,
               currentPlayer.getEvent(),
               currentPlayer.getId());
  
  JSONObject currentPlayerJsonObj2 = setPlayerToJson(currentPlayer,
              currentPlayer.getEvent(),
              currentPlayer.getId());
  
  //build the other players json
     JSONArray currentPlayerArrayNewPlayers = new JSONArray();
     JSONArray ArrayCurrentPlayers = new JSONArray();
     ArrayCurrentPlayers.put(currentPlayerJsonObj2);
     Iterator<Entry<Integer, Player>> it = this.gameManager.getPlayers().entrySet().iterator();
     while (it.hasNext()) {
      @SuppressWarnings("rawtypes")
   Map.Entry pair = (Map.Entry)it.next();
         Player playerIt = ((Player)pair.getValue());
          if(currentPlayerId != playerIt.getId())
         {
          //update each user 
          this.gameManager.getPlayers().get(playerIt.getId()).setDeckcard(currentPlayer.getDeckcard());
          this.gameManager.getPlayers().get(playerIt.getId()).setEvent(Config.PLAY_DONE); 
          this.gameManager.getPlayers().get(playerIt.getId()).setActiveplayerid(newActivePlayer);
          JSONObject playerJsonObjIt = setPlayerToJson(playerIt,
                     Config.PLAY_DONE,
                     playerIt.getId());
          JSONObject newPlayerForCurrent  = setPlayerToJson(playerIt,
                      Config.PLAY_DONE,
                      playerIt.getId());
          currentPlayerArrayNewPlayers.put(newPlayerForCurrent);           
          //to others 
          playerJsonObjIt.put("players",ArrayCurrentPlayers);
          String jsonStr = playerJsonObjIt.toString();
          this.gameManager.getPlayers().get(playerIt.getId()).setPlayerJson(jsonStr);
          
         }        
     }
     //current user array
     currentPlayerJsonObj.put("players",currentPlayerArrayNewPlayers);    
     String jsonStr = currentPlayerJsonObj.toString();
     this.gameManager.getPlayers().get(currentPlayerId).setPlayerJson(jsonStr);
  return true;
 }
 @SuppressWarnings("unused")
 private JSONObject setPlayerToJson(final Player _player,final int event,
          final int _playerId)
 { 
  JSONObject _jsonPlayer = new JSONObject();
  _jsonPlayer.put("id",_playerId);
  _jsonPlayer.put("event",event);
  _jsonPlayer.put("username",_player.getUserName());
  _jsonPlayer.put("activecardid",_player.getActivecardid());
  _jsonPlayer.put("activeplayerid",_player.getActiveplayerid()); 
  _jsonPlayer.put("registertionnum",_player.getRegistertionNum()); 
  _jsonPlayer.put("winner",_player.getWinner()); 
  _jsonPlayer.put("deck",_player.getDeckcard()); 
  _jsonPlayer.put("endgame",_player.getEndgame()); 
  _jsonPlayer.put("winnercards",_player.getWinnercards()); 
  _jsonPlayer.put("numcardsleft",_player.getPlayerCards().size()); 
  return _jsonPlayer;
 }
}


  1. Lines 24 - 49 : Build the response back to the other players about the result of the LOGIN event, the other players will be notified
    about the new player login and also will be receiving the new player data .
    the response event in our super simple game will be with LOGIN_DONE.
  2. Lines 51 -53 : Build the response for the current player . in this case the current player will be
    notified about the other players state if any .
  3. Lines 74 -102 : Build the response back to the other players about the result of the Play event.
    new Event will be send back depending on the Game Play in our Super simple game
    it will return PLAY_DONE event.
  4. Lines 104 - 106 : Build the response for the current player . in this case the current player will be notified about the other players state if any with PLAY_DONE event .
  5. Lines 110 - 125 : Helper function to convert Player data to JSON object.

Now its time to do the Cocos2d-x client code review in the next port:
Multiplayer Card Game using WebSockets,Java Netty Server ,Cocos2d-x-HTML5 - Part 6


Saturday, January 23, 2016

Multiplayer Card Game using WebSockets,Java Netty Server ,Cocos2d-x-HTML5 - Part 4

Game Server Source code overview


Remember the opening of this tutorial i mentioned that one of MMO principles is that the game
is played in the server and not in the client most of the times. to avoid cheating on the client and abusing the game .


In this class the data that is send from the client include events to invoke.
Those events are like "Protocol" between the client and the server both sides should understand them
in our case they are :

Config.java


1
2
3
4
5
6
7
//when the websocket http handshake complete 
 public static final int  HANDSHAKE_COMPLETE_SUCCESS = 1;
 public static final int  LOGIN = 2;
 public static final int  LOGIN_DONE = 3;
 public static final int  NEW_USER_LOGIN_DONE = 4;
 public static final int  PLAY = 5;
 public static final int  PLAY_DONE = 6;


  1. Line 2 : when Websocket protocol is confirmed.
  2. Line 3: Login request form the client .
  3. Line 4: Login is handled , response to client that login is done
  4. Line 5: New User is joined the room 
  5. Line 6: Player is done its turn and played.
  6. Line 7 :Response to all other player and the current player that the turn is done 
GameEventHandler.java

This class will handle the game logic here is where the server "Plays" the game

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
public class GameEventHandler {
 private final static Logger LOG = LoggerManager.GetLogger(GameEventHandler.class.getName());
 private GameManager gameManager; 
 private static int playerIdCounter = 0;
 private static int playerRegistretionCounter = 0;
 public GameEventHandler(GameManager _gameManager)
 {
  this.gameManager = _gameManager;   
 }
 public int handleEvent(String _jsonRequest,Channel channel)
 {
  JSONObject jsonObject = new JSONObject(_jsonRequest);
  int Event = jsonObject.getInt("event");
  int playerId = -1;
  String userName =  jsonObject.getString("username");          
     switch(Event)
     {
         case Config.LOGIN: 
         {             
          Player newPlayer = setPlayerNewAttributes(userName,channel,Config.LOGIN_DONE);
          setPlayerInPlayersContainer(newPlayer);
          playerId = newPlayer.getId();
          break;
         }
         case Config.PLAY:
         {
          playerId = invokePlayEvent(jsonObject);
          
         }
     }
     return playerId;
  }
 public boolean ResponseDispatcher(int _playerId,String _jsonRequest)
 {
  JSONObject jsonObject = new JSONObject(_jsonRequest);
  int Event = jsonObject.getInt("event");
  boolean bDone = false;
  switch(Event)
     {
         case Config.LOGIN: 
         {             
          bDone = this.gameManager.getGameResponseDispatcher().ResponseDispatcheLoginDone(_playerId);
          break;
         }
         case Config.PLAY:
         {
          bDone = this.gameManager.getGameResponseDispatcher().ResponseDispatchePlayDone(_playerId); 
          break;
         }
     }
  
  return bDone;
 }
 private int invokePlayEvent(JSONObject _jsonObject)
 {
  int activePlayerId  = _jsonObject.getInt("id");
  int currentPlayerID = this.gameManager.getPlayers().get(activePlayerId).getActiveplayerid();
  //validation of turn
  if(activePlayerId==currentPlayerID)
  {
   
   //find out who is the previous player
   int playerInx = getPreviousePlayerIndex(currentPlayerID);
   
   
   String currentPlayerCardId = this.gameManager.getPlayers().get(activePlayerId).getActivecardid();
   //check if the cards deck is active in there are cards in it
   if(this.gameManager.getCardsPlayDeck().size()>0)
   {
    String prevCardId = this.gameManager.getCardsPlayDeck().getFirst();
    //check which card has greater value
    int  prevCardValue = this.gameManager.getCardValueById(prevCardId);
    int  currentCardValue = this.gameManager.getCardValueById(currentPlayerCardId);
    //check if previous card is greater
    if(prevCardValue > currentCardValue)
    {
     
     //set the cards to the winner which is previous player
     this.gameManager.getPlayerByIndex(playerInx).getPlayerCards().addLast(currentPlayerCardId);
     this.gameManager.getPlayerByIndex(playerInx).getPlayerCards().addLast(prevCardId);
     //set as winner
     this.gameManager.getPlayerByIndex(playerInx).setWinner(playerInx);
     this.gameManager.getPlayerByIndex(playerInx).setWinnercards(currentPlayerCardId+"_"+prevCardId);
     this.gameManager.getPlayerByIndex(currentPlayerID).setWinner(playerInx);
     this.gameManager.getPlayerByIndex(currentPlayerID).setWinnercards(currentPlayerCardId+"_"+prevCardId);
     
     String currentCartId = this.gameManager.getPlayers().get(activePlayerId).getPlayerCards().getFirst();
     this.gameManager.getPlayers().get(activePlayerId).setActivecardid(currentCartId);
     
     String cardInDeck = this.gameManager.getCardsPlayDeck().getFirst();
     this.gameManager.getPlayerByIndex(playerInx).setDeckcard(cardInDeck);
     this.gameManager.getCardsPlayDeck().clear(); 
     
    }
    //check if current card is greater
    else if(prevCardValue < currentCardValue)
    {
      
      
     String prevPlayerCardId = this.gameManager.getPlayerByIndex(playerInx).getPlayerCards().getFirst();
     this.gameManager.getPlayerByIndex(playerInx).getPlayerCards().removeFirst();
     this.gameManager.getPlayers().get(currentPlayerID).getPlayerCards().addLast(prevPlayerCardId);
     
     //set as winner
     this.gameManager.getPlayerByIndex(playerInx).setWinner(playerInx);
     this.gameManager.getPlayerByIndex(playerInx).setWinnercards(currentPlayerCardId+"_"+prevPlayerCardId);
     this.gameManager.getPlayerByIndex(currentPlayerID).setWinner(playerInx);
     this.gameManager.getPlayerByIndex(currentPlayerID).setWinnercards(currentPlayerCardId+"_"+prevPlayerCardId);
     
     
     String currentCartId = this.gameManager.getPlayerByIndex(playerInx).getPlayerCards().getFirst();
     this.gameManager.getPlayerByIndex(playerInx).setActivecardid(currentCartId);
     
     String cardInDeck = this.gameManager.getCardsPlayDeck().getFirst();
     this.gameManager.getPlayerByIndex(playerInx).setDeckcard(cardInDeck);
     this.gameManager.getCardsPlayDeck().clear();
     
     
    }
    else if(prevCardValue == currentCardValue)
    {
      
     String PreviousePlayerCards[] = getWarCards(playerInx);
     String currentPlayerCards[] = getWarCards(currentPlayerID); 
     
     int  prevCardValue_4 = this.gameManager.getCardValueById(PreviousePlayerCards[3]);
     int  currentCardValue_4 = this.gameManager.getCardValueById(currentPlayerCards[3]);
     //check who is the winner 
     if(prevCardValue_4 > currentCardValue_4)
     {
      String result = CardsArrayToString(PreviousePlayerCards,currentPlayerCards);
      this.gameManager.getPlayerByIndex(playerInx).setWinner(1);
      this.gameManager.getPlayerByIndex(playerInx).setWinnercards(result);
      String currentCartId = this.gameManager.getPlayerByIndex(playerInx).getPlayerCards().getFirst();
      this.gameManager.getPlayerByIndex(playerInx).setActivecardid(currentCartId);
       
     }
     else if(prevCardValue_4 < currentCardValue_4)
     {
      String result = CardsArrayToString(currentPlayerCards,PreviousePlayerCards);
      this.gameManager.getPlayerByIndex(currentPlayerID).setWinner(1);
      this.gameManager.getPlayerByIndex(currentPlayerID).setWinnercards(result);
      String currentCartId = this.gameManager.getPlayerByIndex(currentPlayerID).getPlayerCards().getFirst();
      this.gameManager.getPlayerByIndex(currentPlayerID).setActivecardid(currentCartId);
     }
     else if(prevCardValue_4 == currentCardValue_4)
     {
      //TODO 
      int test =0;
     }
     this.gameManager.getCardsPlayDeck().clear();
    }
   }
   else
   {
    this.gameManager.getCardsPlayDeck().addFirst(currentPlayerCardId);
    this.gameManager.getPlayers().get(activePlayerId).getPlayerCards().removeFirst();
    String currentCartId = this.gameManager.getPlayers().get(activePlayerId).getPlayerCards().getFirst();
    this.gameManager.getPlayers().get(activePlayerId).setActivecardid(currentCartId);
    
    String cardInDeck = this.gameManager.getCardsPlayDeck().getFirst();
    this.gameManager.getPlayers().get(activePlayerId).setDeckcard(cardInDeck);
           
    
   } 
   
   //Check if there are winners for this game
   int prevPlayerCardsSize = this.gameManager.getPlayerByIndex(playerInx).getPlayerCards().size();
   if(prevPlayerCardsSize==0)
   {
    //game is ended
    this.gameManager.getPlayerByIndex(playerInx).setEndgame(currentPlayerID);
    this.gameManager.getPlayerByIndex(currentPlayerID).setEndgame(currentPlayerID);
    
   }
  }
  else
  {
   activePlayerId =-1;
  }
  return activePlayerId;
 }
 private String CardsArrayToString(String[] cardsPrev,String[] cardsCurrent)
 {
  String result ="";
  for (String s: cardsPrev) {           
         //Do your stuff here
   result+=s;
   result+="_";
     }
  for (String s: cardsCurrent) {           
         //Do your stuff here
   result+=s;
   result+="_";
     }
  result = result.substring(0, result.length()-1);
  return result;
 }
 private String[] getWarCards(int playerID)
 { 
  String prevPlayerCardId_1 = this.gameManager.getPlayerByIndex(playerID).getPlayerCards().getFirst();
  this.gameManager.getPlayerByIndex(playerID).getPlayerCards().removeFirst();
  String prevPlayerCardId_2 = this.gameManager.getPlayerByIndex(playerID).getPlayerCards().getFirst();
  this.gameManager.getPlayerByIndex(playerID).getPlayerCards().removeFirst();
  String prevPlayerCardId_3 = this.gameManager.getPlayerByIndex(playerID).getPlayerCards().getFirst();
  this.gameManager.getPlayerByIndex(playerID).getPlayerCards().removeFirst();
  //the fourth card is to play the war
  String prevPlayerCardId_4 = this.gameManager.getPlayerByIndex(playerID).getPlayerCards().getFirst();
  this.gameManager.getPlayerByIndex(playerID).getPlayerCards().removeFirst();
  return new String[]{prevPlayerCardId_1, prevPlayerCardId_2,prevPlayerCardId_3,prevPlayerCardId_4};
 }
 private int getPreviousePlayerIndex(int _currentPlayerID)
 {
  //find out who is the previous player
  int playerInx = this.gameManager.getPlayerIndexByKey(_currentPlayerID);
  if(playerInx == 0)
  {
   int playerSize = this.gameManager.getPlayers().size();
   playerInx = playerSize-1;
  }
  else
  {
   --playerInx;
  }
  return playerInx;
 }
 private Player setPlayerNewAttributes(String _userName,Channel channel,int nextEvent)
 {
  Player newPlayer = new Player(channel);
  newPlayer.setUserName(_userName);
  int id = GenerateUniqueId(); 
  int count = getPlayerRegistretionCounter();
  newPlayer.setRegistertionNum(count);
  newPlayer.setId(id);
  newPlayer.setEvent(nextEvent);
  setPlayerCards(newPlayer);
  setNewPlayerCardId(newPlayer);
  return newPlayer;
 }
 
 private void setPlayerInPlayersContainer(Player _player)
 {
  this.gameManager.getPlayers().put(_player.getId(), _player);
 }
 private void setPlayerCards(Player _player)
 {
  //this is only good for 2 players 
  int len = this.gameManager.getCardsRandomize().length-1;
  if(_player.getId()==0)
  {   
   for(int i=0;i<(len/2);i++)
   {
    _player.getPlayerCards().push(this.gameManager.getCardsRandomizeByIndex(i));
   }
  }
  else if(_player.getId()==1)
  {
   for(int i=len;i>(len/2);i--)
   {
    _player.getPlayerCards().push(this.gameManager.getCardsRandomizeByIndex(i));
   }
  }
 }
 private void setNewPlayerCardId(Player _player)
 {
  String cardId = _player.getPlayerCards().removeFirst();
  _player.setActivecardid(cardId);
 }
 
 private int GenerateUniqueId()
 {
  int id = this.playerIdCounter;
  this.playerIdCounter++;
  return id;
 }
 
 private int getPlayerRegistretionCounter()
 {
  int count = this.playerRegistretionCounter;
  this.playerRegistretionCounter++;
  return count;
 }
  
}
hshshhs

  1. Lines 18 -24: In this simple card game we have 2 main events first is when player login to the game .
    And the second is when player plays it turn .
    This is where the first case get handled.the client sent the server LOGIN event .
    And the Server do several things:
    A. Creates new Player object
    B. Updates the Player properties
    C. Set the Player object into the Players Container ( in GameManger object ) .
    D. Associate unique id to the player.
  2. Lines 25 -29: The second event as mentioned in the previous section,is when the player makes
    its turn . the client will send the PLAY event .
    when this event triggered in the server , the server will play the game and update the game states for each other players in the game.
  3. Lines 33 - 50: This function will dispatch the response according to the Event that is currently
    get handled by the server.
  4. Lines 56 -59: The invokePlayEvent is big function , it handles the game logic and updates The other players (in the server ) with the new game states .
    First we need to know that the player which we handling is the one that playing now its turn.
    in the JSON structure that is passing between the client and the server
    and also on of the Player Member called : activeplayerid .This member will hold the id of the Player that is currently playing .
  5. Lines 63 -66: Get the previous player. this is turn based game so we need to check what did the previous player done , and to compare between the current Player status and the previous Player Status.
  6. Lines 75 - 92: In our game there could be 2 states in the game:
    First when the middle card deck is empty and one of the players should play its turn
    Second is when there is already a card on the middle deck so the player now should:
    A. Play its card.
    B. Compare between this current player card and the previous player card .

    Here we check if the previous card is greater then current player card .
    Then the following actions are made in the server :
    A.Update the winner player ( previous player ) with the winning cards.
    B.Update the current player about the winner player.
    C.Clear the middle card deck.
  7. Lines 96 -116: Check if the current player is the winner by comparing the cards values
    and doing the same as we did in section 6 above . but this time set current player as winner.
  8. Lines 120 - 145: Check if the cards value are the same , in this case  the War Card game rule
    is that we take 4 cards from each player (lines: 123 -124). and the last (lines 126 -127 ) card
    is the card that we are going to check .
    Again like in sections 6. and 7. the cards values is compared to determine who is the winner .
  9. Lines 146 -150: to keep this code simple as possible the game support only 1 level of WAR state . so if there is again WAR between the cards there is a need to implement the WAR handling again . maybe to separate it to sub-function and call it again  .
    i leave it to you as exercise  ...
  10. Lines 156 - 162: This is the case where the previous player didn't played , so the current player
    is the one that play first. that means putting the card on the middle card deck.
    A.Update the middle card deck with current player card.
    B.Remove the played card from the player card stack.
    C.Update the other player with the card which played.
  11. Lines 168 -173: To determine who is the winner in the game the logic is to check if the previous players card stack is empty , if its empty so the current player is the winner .
    and the game Ended.
    of course we need to update the players and the server that the game is ended .
    by setting the player member : endgame with the winning player id .




    Now we are ready to learn how the response to clients is dispatched . in the next post:

    Multiplayer Card Game using WebSockets,Java Netty Server ,Cocos2d-x-HTML5 - Part 5