Game Server Source code overview
Tutorial Source code :
TextWebSocketFrameHandler.java
This class has 2 parts.the first part will invoke the WebSocket HandShake mechanism that send confirmation back to the client so the connection will be upgraded to open TCP socket connection .
The second part will handle the WebSocket Request and decode the incoming text to massage text for the Game Server to handle.
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 | public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{ private final static Logger LOG = LoggerManager.GetLogger(GameServerMain.class.getName()); private GameManager gameManager; private GameEventHandler gameEventHandler; public TextWebSocketFrameHandler(GameManager _gameManager,GameEventHandler _gameEventHandler) { this.gameManager = _gameManager; this.gameEventHandler = _gameEventHandler; } public TextWebSocketFrameHandler() { ; } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE) { ctx.pipeline().remove(HttpRequestHandler.class); JSONObject responseJson = new JSONObject(); responseJson.put("event",Config.HANDSHAKE_COMPLETE_SUCCESS); LOG.severe("HANDSHAKE_COMPLETE "+responseJson.toString()); ctx.channel().writeAndFlush(new TextWebSocketFrame(responseJson.toString())); } else { super.userEventTriggered(ctx, evt); } } @Override public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { msg.retain(); TextWebSocketFrame frame = (TextWebSocketFrame) msg; String jsonRequest = frame.text(); LOG.severe("Recived from client :"+jsonRequest); try { int playerId = this.gameEventHandler.handleEvent(jsonRequest,ctx.channel()); if(playerId !=-1) { this.gameEventHandler.ResponseDispatcher(playerId,jsonRequest); 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()); String PlayerMassage = playerIt.getPlayerJson().toString(); responseToClient(playerIt,PlayerMassage); LOG.severe("Sending to client id:"+String.valueOf(playerIt.getId())+" name:"+playerIt.getUserName()+" json:" +PlayerMassage); } } else { LOG.severe("Sending to clients Failed playerId is -1"); } } finally { frame.release(); } } private void responseToClient(Player _player,String responseJson) { _player.getChannel().writeAndFlush(new TextWebSocketFrame(responseJson)); } } |
- Lines 14 - 23 : this is the WebSocket Handshak , remember the WebSocket dialog sequence between the client and the server performed in this order :
A .the client send HTTP request to see if the server support WebSocket
and inform the server the future connection type is WebSocket ,
B. if confirmed by the server the connection is UPGRADED to TCP open connection between the client and the server , - Lines 28 - 29: the incoming request from the client as string.
- Line 32: send the string to Game Event Handler , which is a object that handle events and according to the event type it constructing and sending the response's back to the clients.
- Lines 35 - 44 : handle the response and send them back to the clients which are connected .
- Lines 55 - 58 : write the actual WebSocket Frame to the open connection channel.
WebSocket Frame is encapsolated Netty object that handle WebSocket data .
this is helper function which using the player Channel member to send the data .
This class Is the "glue" that connects all the game logic It holds the Cards Map.
And the players map container and the response dispatcher.
and it should also have the Game event Handler which will be done in the next version .
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 | public class GameManager { private final static Logger LOG = LoggerManager.GetLogger(GameServerMain.class.getName()); private final String[] cardsNotRandomBase = {"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12","c13","c14","c15","c16","c17","c18","c19","c20","c21","c22","c23","c24","c25","c26","c27","c28","c29","c30","c31","c32","c33","c34","c35","c36","c37","c38","c39","c40","c41","c42","c43","c44","c45","c46","c47","c48","c49","c50","c51","c52","c53"}; private final String[] cardsRandomize; public final HashMap<String, String> cardsMap; private volatile Map<Integer, Player> players; private LinkedList<String> cardsPlayDeck; private final GameResponseDispatcher gameResponseDispatcher; public GameManager( ) { cardsMap = new HashMap<String, String>(); setCardsHash(); final ResourceBundle configurationBundle = ResourceBundle.getBundle("configuration"); //hashmap with predictable iteration order players = new LinkedHashMap<Integer, Player>(); cardsPlayDeck = new LinkedList<String>(); this.cardsRandomize = Arrays.copyOf(cardsNotRandomBase , cardsNotRandomBase .length); Collections.shuffle(Arrays.asList(cardsRandomize)); gameResponseDispatcher = new GameResponseDispatcher(this); } public GameResponseDispatcher getGameResponseDispatcher() { return gameResponseDispatcher; } public HashMap<String, String> getCardsMap() { return cardsMap; } public LinkedList<String> getCardsPlayDeck() { return cardsPlayDeck; } public void setCardsPlayDeck(LinkedList<String> cardsPlayDeck) { this.cardsPlayDeck = cardsPlayDeck; } public int getPlayerIndexByKey(int playerKey) { int pos = new ArrayList<Integer>(players.keySet()).indexOf(playerKey); return pos; } public Player getPlayerByIndex(int inx) { List<Player> l = new ArrayList<Player>(players.values()); Player p = l.get(inx); return p; } public Map<Integer, Player> getPlayers() { return players; } public void setPlayers(Map<Integer, Player> players) { this.players = players; } public String[] getCardsRandomize() { return cardsRandomize; } public String getCardsRandomizeByIndex(int i) { return cardsRandomize[i]; } public int getCardValueById(String cardId) { String card = this.cardsMap.get(cardId); String rightPart= card.split("_")[1]; String number = rightPart.split(".png")[0]; int cardIntVal = Integer.valueOf(number); return cardIntVal; } public int getNextActivePlayer(int currentActivePlayer) { int currentPlyInx = getPlayerIndexByKey(currentActivePlayer); int activePlayer = 0; if(currentPlyInx < (players.size()-1)) { ++activePlayer; } return activePlayer; } private void setCardsHash() { cardsMap.put("c1","cardClubsA_20.png"); cardsMap.put("c2","cardClubsJ_17.png"); cardsMap.put("c3","cardClubsK_19.png"); cardsMap.put("c4","cardClubsQ_18.png"); cardsMap.put("c5","cardDiamonds10_10.png"); cardsMap.put("c6","cardDiamonds2_2.png"); cardsMap.put("c7","cardDiamonds3_3.png"); cardsMap.put("c8","cardDiamonds4_4.png"); cardsMap.put("c9","cardDiamonds5_5.png"); cardsMap.put("c10","cardDiamonds6_6.png"); cardsMap.put("c11","cardDiamonds7_7.png"); cardsMap.put("c12","cardDiamonds8_8.png"); cardsMap.put("c13","cardDiamonds9_9.png"); cardsMap.put("c14","cardDiamondsA_20.png"); cardsMap.put("c15","cardDiamondsJ_17.png"); cardsMap.put("c16","cardDiamondsK_19.png"); cardsMap.put("c17","cardDiamondsQ_18.png"); cardsMap.put("c18","cardHearts10_10.png"); cardsMap.put("c19","cardHearts2_2.png"); cardsMap.put("c20","cardHearts3_3.png"); cardsMap.put("c21","cardHearts4_4.png"); cardsMap.put("c22","cardHearts5_5.png"); cardsMap.put("c23","cardHearts6_6.png"); cardsMap.put("c24","cardHearts7_7.png"); cardsMap.put("c25","cardHearts8_8.png"); cardsMap.put("c26","cardHearts9_9.png"); cardsMap.put("c27","cardHeartsA_20.png"); cardsMap.put("c28","cardHeartsJ_17.png"); cardsMap.put("c29","cardHeartsK_19.png"); cardsMap.put("c30","cardHeartsQ.png"); cardsMap.put("c31","cardJoker_21.png"); cardsMap.put("c32","cardSpades10_10.png"); cardsMap.put("c33","cardSpades2_2.png"); cardsMap.put("c34","cardSpades3_3.png"); cardsMap.put("c35","cardSpades4_4.png"); cardsMap.put("c36","cardSpades5_5.png"); cardsMap.put("c37","cardSpades6_6.png"); cardsMap.put("c38","cardSpades7_7.png"); cardsMap.put("c39","cardSpades8_8.png"); cardsMap.put("c40","cardSpades9_9.png"); cardsMap.put("c41","cardSpadesA_20.png"); cardsMap.put("c42","cardSpadesJ_17.png"); cardsMap.put("c43","cardSpadesK_19.png"); cardsMap.put("c44","cardSpadesQ_18.png"); cardsMap.put("c45","cardClubs10_10.png"); cardsMap.put("c46","cardClubs2_2.png"); cardsMap.put("c47","cardClubs3_3.png"); cardsMap.put("c48","cardClubs4_4.png"); cardsMap.put("c49","cardClubs5_5.png"); cardsMap.put("c50","cardClubs6_6.png"); cardsMap.put("c51","cardClubs7_7.png"); cardsMap.put("c52","cardClubs8_8.png"); cardsMap.put("c53","cardClubs9_9.png"); } } |
- Line 3 : array of the cards. those are the key names of the game cards are sorted by order.
- Line 5 : the map which maps between the cards names and the cards key names.
- Line 6 : the players container from type Ordered Map . the key set by the order the player login.
- Line 7: is the deck of cards in between the players,where each player show its cards in its turn.
- Lines 17-18:shuffle the cards .
- The rest are just simple small helper functions and getters and setters that are self explanatory.
Next we going to analize the game logic continue to the next post :
Multiplayer Card Game using WebSockets,Java Netty Server ,Cocos2d-x-HTML5 - Part 4
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.