For the first two, we have implemented the login screen and the main screen of the game. However, the data of the main interface of the game is written dead text in the front end. In this chapter, we add websocket component to the game module to realize the communication between the front and back end, so that the data of the front end can be dynamically obtained from the back end.

Add maven dependencies

In the POM of the Game module, we added three dependency packages as follows:

1 <! -- WebSocket component --> 2 <dependency> 3 <groupId>org. springFramework </groupId> 4 <artifactId> Spring-websocket </artifactId> 5 <version>5.1.6.RELEASE</version> 6 </dependency> 7 <dependency> 8 <groupId>org. springFramework </groupId> 9 <artifactId>spring- Messaging </artifactId> 10 <version>5.1.6.RELEASE</version> 11 </dependency> 12 <dependency> 13 <groupId>javax.websocket</groupId> 14 <artifactId>javax.websocket- API </artifactId> 15 <version>1.1</version> 16 <scope>provided</scope> 17 </dependency>Copy the code

2. Add MessageHub to the backend

Under com.idlewow.game.hub MessageHub, this class will be responsible for receiving websocket information from the client. The code is as follows:

1 @Component 2 @ServerEndpoint(value = "/hub", configurator = HttpSessionConfigurator.class) 3 public class MessageHub { 4 private static final Logger logger = LogManager.getLogger(MessageHub.class); 5 6 @Autowired 7 MessageHandler messageHandler; 8 @Autowired 9 CharacterService characterService; 10 11 @OnOpen 12 public void onOpen(Session session, EndpointConfig config) {13 Logger. info("[websocket][" + session.getid () + "] Establish connection "); 14 try { 15 HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getSimpleName()); 16 If (httpSession == null) {17 Logger. error("[websocket][" + session.getid () + "] failed to fetch httpSession! ); 18 throw new Exception(" Failed to get HttpSession!" ); 19 } 20 21 22 if (httpSession.getAttribute(GameWorld.SK_CharId) == null) { 23 logger.error("[websocket][" + Session.getid () + "] Get role Id null!" ); 24 Throw new Exception(" Get role ID null!" ); 25 } 26 27 String charId = httpSession.getAttribute(GameWorld.SK_CharId).toString(); 28 CommonResult commonResult = characterService.find(charId); 29 if (commonResult.isSuccess()) { 30 Character character = (Character) commonResult.getData(); 31 / * loaded successfully, add cache * / 32 GameWorld OnlineSession. Add (session); 33 GameWorld.OnlineCharacter.put(session.getId(), character); 34 GameWorld.MapCharacter.get(character.getMapId()).add(character); 35} else {36 Logger. error(" Failed to load role info! charId:" + charId + " message:" + commonResult.getMessage()); 37 Throw new Exception(" Failed to load role information!" ); 38} 39} catch (Exception ex) {40 logger.error("[websocket][" + session.getid () + "]) : "+ ex.getMessage(), ex); 41 this.closeSession(session, ex.getMessage()); 42 } 43 } 44 45 @OnMessage 46 public void onMessage(Session session, String message) {47 Logger. info("[websocket][" + session.getid () + "] receive message: "+ message); 48 messageHandler.handleMessage(session, message); 49 } 50 51 @OnClose 52 public void onClose(Session session) { 53 logger.info("[websocket][" + session.getId() + "] close connection "); 54 / * clear the cache * / 55 Character Character. = GameWorld OnlineCharacter. Get (session. The getId ()); 56 GameWorld.OnlineSession.remove(session); 57 GameWorld.OnlineCharacter.remove(session.getId()); 58 GameWorld.MapCharacter.get(character.getMapId()).remove(character); 59 } 60 61 @OnError 62 public void onError(Session session, Throwable t) {63 logger.error("[websocket][" + session.getid () + "] : "+ t.gettmessage (), t); 64 } 65 66 private void closeSession(Session session, String message) {67 try {68 logger.info("[websocket][" + session.getid () + "] closes connection, cause: "+ message); 69 CloseReason closeReason = new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, message); 70 session.close(closeReason); 71} catch (Exception ex) {72 logger.error("[websocket] closed connection Exception: "+ ex.getMessage(), ex); 73} 74} 75}Copy the code

MessageHub

Hub class mainly includes OnOpen, OnMessage, OnClose, OnError four methods.

When OnOpen establishes a connection, we get the role Id from HttpSession, load the role information, update the online data, and so on. Here we create a GameWorld class to store the global static data of the GameWorld, such as the online list.

When the OnMessage method receives the client data, we process the message uniformly in the MessageHandler.

OnClose and OnError correspond to closing the connection and exception occurrence events. When closing the connection, you need to clear the game character from the online list. When an exception occurs, we simply log for the time being.

Note: In the annotation for MesssageHub, we have configured it with a HttpSessionConfigurator. To get HttpSession data in the socket message. Without this configuration, HttpSession is not available. The code is as follows:

1 public class HttpSessionConfigurator extends SpringConfigurator { 2 @Override 3 public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { 4 HttpSession httpSession = (HttpSession) request.getHttpSession(); 5 sec.getUserProperties().put(HttpSession.class.getSimpleName(), httpSession); 6 super.modifyHandshake(sec, request, response); 8 7}}Copy the code

Define the message type

In socket communication, we must define the data structure of the message and prepare corresponding documents to facilitate the communication between the front and back ends.

Here we create the message class WowMessage and specify that it consists of header and Content. Header contains general parameters such as message type and request time. Content contains specific business data.

The UML diagram of the whole message class is as follows, which exemplifies four specific message types: LoadCache cache loading, Login Login message, Chat Chat message, Move map Move message.

  

 

4. Back-end message processing

 

Once the good news type is defined, we can process the corresponding message in the back end. The code is as follows:

In the handleMessage method, we determine what kind of message it is, based on the messageCode passed in the header, and pass it to the corresponding handler submethod.

For example, the handleMoveMessage method is used to process map movement. In this method, we change the current map ID in the character information cache data to the map ID after moving, remove this role from the original map online list, and add this role to the target map online list. And returns the target map information to the front end for display.

@Component
public class MessageHandler {
    private static final Logger logger = LogManager.getLogger(MessageHandler.class);

    @Autowired
    CharacterService characterService;
    @Autowired
    WowMapService wowMapService;
    @Autowired
    MapMobService mapMobService;
    @Autowired
    MapCoordService mapCoordService;

    /**
     * 消息处理
     *
     * @param session session
     * @param message 消息
     */
    public void handleMessage(Session session, String message) {
        WowMessage<?> wowMessage = JSONObject.parseObject(message, WowMessage.class);
        WowMessageHeader header = wowMessage.getHeader();
        String messageCode = header.getMessageCode();
        switch (messageCode) {
            case WowMessageCode.LoadCache:
                this.handleLoadCacheMessage(session, (WowMessage<LoadCacheRequest>) wowMessage);
                break;
            case WowMessageCode.RefreshOnline:
                this.handleRefreshOnlineMessage(session, (WowMessage<RefreshOnlineRequest>) wowMessage);
                break;
            case WowMessageCode.Login:
                this.handleLoginMessage(session, (WowMessage<LoginRequest>) wowMessage);
                break;
            case WowMessageCode.Chat:
                this.handleChatMessage(session, (WowMessage<ChatRequest>) wowMessage);
                break;
            case WowMessageCode.Move:
                this.handleMoveMessage(session, (WowMessage<MoveRequest>) wowMessage);
                break;
            default:
                break;
        }
    }

    /**
     * 给指定客户端发送消息
     *
     * @param session 客户端session
     * @param message 消息内容
     */
    private void sendOne(Session session, String message) {
        try {
            session.getBasicRemote().sendText(message);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }

    /**
     * 给所有客户端发送消息
     *
     * @param message 消息内容
     */
    private void sendAll(String message) {
        try {
            for (Session session : GameWorld.OnlineSession) {
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }

    /**
     * 登陆加载
     *
     * @param session session
     * @param message 消息
     */
    private void handleLoginMessage(Session session, WowMessage<LoginRequest> message) {
        WowMessageHeader header = message.getHeader();
        header.setResponseTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        LoginResponse response = new LoginResponse();
        Character character = GameWorld.OnlineCharacter.get(session.getId());
        String mapId = character.getMapId();
        MapInfo mapInfo = this.loadMapInfo(mapId);
        response.setMapInfo(mapInfo);
        OnlineInfo onlineInfo = this.loadOnlineInfo(mapId);
        response.setOnlineInfo(onlineInfo);
        WowMessage wowMessage = new WowMessage<>(header, response);
        this.sendOne(session, JSON.toJSONString(wowMessage));
    }

    /**
     * 发送聊天
     *
     * @param session session
     * @param message 消息
     */
    private void handleChatMessage(Session session, WowMessage<ChatRequest> message) {
        WowMessageHeader header = message.getHeader();
        header.setResponseTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        ChatRequest request = message.getContent();
        ChatResponse response = new ChatResponse();
        response.setSendId(request.getSendId());
        response.setSendName(request.getSendName());
        response.setRecvId(request.getRecvId());
        response.setRecvName(request.getRecvName());
        response.setMessage(request.getMessage());
        response.setChannel(request.getChannel());
        WowMessage wowMessage = new WowMessage<>(header, response);
        if (request.getChannel().equals(GameWorld.ChatChannel.WORLD)) {
            this.sendAll(JSON.toJSONString(wowMessage));
        } else if (request.getChannel().equals(GameWorld.ChatChannel.PRIVATE)) {
            // todo 发送消息给指定玩家
        } else if (request.getChannel().equals(GameWorld.ChatChannel.LOCAL)) {
            // todo 发送消息给当前地图玩家
        }
    }

    /**
     * 加载缓存
     *
     * @param session session
     * @param message 消息
     */
    private void handleLoadCacheMessage(Session session, WowMessage<LoadCacheRequest> message) {
        WowMessageHeader header = message.getHeader();
        header.setResponseTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        LoadCacheResponse response = new LoadCacheResponse();
        Map<String, Integer> levelExpMap = new HashMap<>();
        for (Integer key : CacheUtil.levelExpMap.keySet()) {
            levelExpMap.put(key.toString(), CacheUtil.levelExpMap.get(key));
        }

        response.setLevelExpMap(levelExpMap);
        WowMessage wowMessage = new WowMessage<>(header, response);
        this.sendOne(session, JSON.toJSONString(wowMessage));
    }

    /**
     * 地图移动
     *
     * @param session session
     * @param message 消息
     */
    private void handleMoveMessage(Session session, WowMessage<MoveRequest> message) {
        WowMessageHeader header = message.getHeader();
        header.setResponseTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        MoveRequest request = message.getContent();
        Character character = GameWorld.OnlineCharacter.get(session.getId());
        String fromMapId = character.getMapId();
        String destMapId = request.getDestMapId();
        GameWorld.MapCharacter.get(fromMapId).remove(character);
        GameWorld.MapCharacter.get(destMapId).add(character);
        character.setMapId(destMapId);
        MapInfo mapInfo = this.loadMapInfo(destMapId);
        OnlineInfo onlineInfo = this.loadOnlineInfo(destMapId);
        MoveResponse response = new MoveResponse();
        response.setMapInfo(mapInfo);
        response.setOnlineInfo(onlineInfo);
        WowMessage wowMessage = new WowMessage<>(header, response);
        this.sendOne(session, JSON.toJSONString(wowMessage));
    }

    /**
     * 刷新在线列表
     *
     * @param session session
     * @param message 消息
     */
    private void handleRefreshOnlineMessage(Session session, WowMessage<RefreshOnlineRequest> message) {
        WowMessageHeader header = message.getHeader();
        header.setResponseTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        Character character = GameWorld.OnlineCharacter.get(session.getId());
        String mapId = character.getMapId();
        OnlineInfo onlineInfo = this.loadOnlineInfo(mapId);
        RefreshOnlineResponse response = new RefreshOnlineResponse();
        response.setOnlineInfo(onlineInfo);
        WowMessage wowMessage = new WowMessage<>(header, response);
        this.sendOne(session, JSON.toJSONString(wowMessage));
    }

    /**
     * 读取地图信息
     *
     * @param mapId 地图ID
     * @return
     */
    private MapInfo loadMapInfo(String mapId) {
        MapInfo mapInfo = new MapInfo();
        CommonResult commonResult = wowMapService.find(mapId);
        if (commonResult.isSuccess()) {
            WowMap wowMap = (WowMap) commonResult.getData();
            mapInfo.setWowMap(wowMap);
        }

        List<MapCoord> mapCoordList = mapCoordService.listByFromMapId(mapId);
        mapInfo.setMapCoordList(mapCoordList);

        return mapInfo;
    }

    /**
     * 读取在线列表
     *
     * @param mapId 地图ID
     * @return
     */
    private OnlineInfo loadOnlineInfo(String mapId) {
        OnlineInfo onlineInfo = new OnlineInfo();
        List<MapMob> mapMobList = mapMobService.listByMapId(mapId);
        onlineInfo.setMapMobList(mapMobList);
        List<Character> mapCharacterList = GameWorld.MapCharacter.get(mapId);
        onlineInfo.setMapCharacterList(mapCharacterList);
        return onlineInfo;
    }
}
Copy the code

MessageHandler

Fifth, front-end socket processing

Corresponding to the backend MessageHub, the front-end also needs a socket client, here we create a WowClient object, responsible for the outermost message processing logic.

1 const WowClient = function () { 2 this.cache = { 3 version: 0, 4 levelExpMap: [] 5 }; 6 this.cacheKey = "idlewow_client_cache"; 7 this.hubUrl = "ws://localhost:20010/hub"; 8 this.webSocket = new WebSocket(this.hubUrl); 9 this.websocket. onopen = function (event) {10 console.log(' webSocket establishes connection '); 11 wowClient.sendLogin(); 12 wowClient.loadCache(); 13}; 14 this.websocket. onMessage = function (event) {15 console.log(' webSocket received message: % C '+ event. 'color:green'); 16 var message = JSON.parse(event.data) || {}; 17 console.log(message); 18 wowClient.receive(message); 19}; 20 this.websocket. onclose = function (event) {21 console.log(' webSocket closes connection '); 22}; 23 this.websocket. onerror = function (event) {24 console.log(' webSocket error '); 25}; 26};Copy the code

In addition, the front end also needs to define message types,

1 const RequestMessage = function () { 2 this.header = { 3 messageCode: "", 4 requestTime: new Date(), 5 version: "1.0", 6}; 7 this.content = {}; 8}; 9 10 const MessageCode = {11 // pre-processing 12 LoadCache: "0010", 13 // system command 14 Login: "1001", 15 RefreshOnline: "1002", 16 // Player commands 17 Chat: "2001", 18 Move: "2002", 19 BattleMob: "2100" 20};Copy the code

The creation of concrete message processing logic and message entities is generated through the stereotype method. The complete js file is as follows:

  1 const WowClient = function () {
  2     this.cache = {
  3         version: 0,
  4         levelExpMap: []
  5     };
  6     this.cacheKey = "idlewow_client_cache";
  7     this.hubUrl = "ws://localhost:20010/hub";
  8     this.webSocket = new WebSocket(this.hubUrl);
  9     this.webSocket.onopen = function (event) {
 10         console.log('WebSocket建立连接');
 11         wowClient.sendLogin();
 12         wowClient.loadCache();
 13     };
 14     this.webSocket.onmessage = function (event) {
 15         console.log('WebSocket收到消息:%c' + event.data, 'color:green');
 16         var message = JSON.parse(event.data) || {};
 17         console.log(message);
 18         wowClient.receive(message);
 19     };
 20     this.webSocket.onclose = function (event) {
 21         console.log('WebSocket关闭连接');
 22     };
 23     this.webSocket.onerror = function (event) {
 24         console.log('WebSocket发生异常');
 25     };
 26 };
 27 
 28 const RequestMessage = function () {
 29     this.header = {
 30         messageCode: "",
 31         requestTime: new Date(),
 32         version: "1.0"
 33     };
 34     this.content = {};
 35 };
 36 
 37 const MessageCode = {
 38     // 预处理
 39     LoadCache: "0010",
 40     // 系统命令
 41     Login: "1001",
 42     RefreshOnline: "1002",
 43     // 玩家命令
 44     Chat: "2001",
 45     Move: "2002",
 46     BattleMob: "2100"
 47 };
 48 
 49 WowClient.prototype = {
 50     //////////////////
 51     //// 对外接口 ////
 52     //////////////////
 53     // 读取缓存
 54     loadCache: function () {
 55         let storage = localStorage.getItem(this.cacheKey);
 56         let cache = storage ? JSON.parse(storage) : null;
 57         if (!cache || (new Date().getTime() - cache.version) > 1000 * 60 * 60 * 24) {
 58             this.sendLoadCache();
 59         } else {
 60             this.cache = cache;
 61         }
 62     },
 63 
 64     //////////////////
 65     //// 消息处理 ////
 66     //////////////////
 67 
 68     // 发送消息
 69     send: function (message) {
 70         let msg = JSON.stringify(message);
 71         this.webSocket.send(msg);
 72     },
 73     // 接收消息
 74     receive: function (message) {
 75         switch (message.header.messageCode) {
 76             case MessageCode.LoadCache:
 77                 this.recvLoadCache(message);
 78                 break;
 79             case MessageCode.RefreshOnline:
 80                 this.recvRefreshOnline(message);
 81                 break;
 82             case MessageCode.Login:
 83                 this.recvLogin(message);
 84                 break;
 85             case MessageCode.Chat:
 86                 this.recvChat(message);
 87                 break;
 88             case MessageCode.Move:
 89                 this.recvMove(message);
 90                 break;
 91             case MessageCode.BattleMob:
 92                 this.recvBattleMob(message);
 93                 break;
 94             default:
 95                 break;
 96         }
 97     },
 98 
 99     // 读取缓存
100     sendLoadCache: function () {
101         this.send(new RequestMessage().loadCache());
102     },
103     recvLoadCache: function (message) {
104         this.cache.levelExpMap = message.content.levelExpMap;
105         this.cache.version = new Date().getTime();
106         localStorage.setItem(this.cacheKey, JSON.stringify(this.cache));
107     },
108     // 刷新在线列表
109     sendRefreshOnline: function () {
110         this.send(new RequestMessage().refreshOnline());
111     },
112     recvRefreshOnline: function (message) {
113         this.refreshOnlineInfo(message.content.onlineInfo);
114     },
115     // 登陆
116     sendLogin: function () {
117         this.send(new RequestMessage().login());
118     },
119     recvLogin: function (message) {
120         this.refreshMapInfo(message.content.mapInfo);
121         this.refreshOnlineInfo(message.content.onlineInfo);
122     },
123     // 聊天
124     sendChat: function () {
125         this.send(new RequestMessage().chat());
126     },
127     recvChat: function (message) {
128         let channel = "【当前】";
129         let content = "<p>" + channel + message.content.senderName + ": " + message.content.message + "</p>";
130         $('.msg-chat').append(content);
131     },
132     // 移动
133     sendMove: function (mapId) {
134         this.send(new RequestMessage().move(mapId));
135     },
136     recvMove: function (message) {
137         this.refreshMapInfo(message.content.mapInfo);
138         this.refreshOnlineInfo(message.content.onlineInfo);
139     },
140     // 战斗
141     sendBattleMob: function (mobId) {
142         this.send(new RequestMessage().battleMob(mobId));
143     },
144     recvBattleMob: async function (message) {
145         $('.msg-battle').html('');
146         let battleResult = message.content.battleResult;
147         if (battleResult.roundList) {
148             var rounds = battleResult.roundList;
149             for (var i = 0; i < rounds.length; i++) {
150                 var round = rounds[i];
151                 var content = "<p>【第" + round.round + "回合】</p>";
152                 if (round.atkStage) {
153                     content += "<p>" + round.atkStage.desc + "</p>";
154                 }
155 
156                 if (round.defStage) {
157                     content += "<p>" + round.defStage.desc + "</p>";
158                 }
159 
160                 $('.msg-battle').append(content);
161                 await this.sleep(1500);
162             }
163 
164             $('.msg-battle').append("<p><strong>战斗结束," + battleResult.winName + " 获得胜利!</strong></p>");
165             if (battleResult.isPlayerWin) {
166                 this.settlement(battleResult);
167             }
168 
169             let that = this;
170             await this.sleep(5000).then(function () {
171                 that.sendBattleMob(battleResult.atkId, battleResult.defId);
172             });
173         }
174     },
175 
176     //////////////////
177     //// 辅助方法 ////
178     //////////////////
179 
180     // 刷新地图信息
181     refreshMapInfo: function (mapInfo) {
182         let wowMap = mapInfo.wowMap;
183         let mapCoordList = mapInfo.mapCoordList;
184         $('#mapName').html(wowMap.name);
185         $('#mapDesc').html(wowMap.description);
186         $('#mapImg').attr('src', '/images/wow/map/' + wowMap.name + '.jpg');
187         let coordsHtml = '';
188         for (let index in mapCoordList) {
189             let mapCoord = mapCoordList[index];
190             coordsHtml += '<area shape="' + mapCoord.shape + '" coords="' + mapCoord.coord + '" onclick="wowClient.sendMove(\'' + mapCoord.destMapId + '\');" href="javascript:void(0);" alt="' + mapCoord.destMapName + '" title="' + mapCoord.destMapName + '"/>';
191         }
192 
193         $('#map-coords').html(coordsHtml);
194     },
195     // 刷新在线列表
196     refreshOnlineInfo: function (onlineInfo) {
197         let mapCharacterList = onlineInfo.mapCharacterList;
198         let mapMobList = onlineInfo.mapMobList;
199         // 更新在线列表
200         $('#online-all').html('');
201         $('#online-player').html('');
202         $('#online-mob').html('');
203         for (let index in mapCharacterList) {
204             let mapCharacter = mapCharacterList[index];
205             let row = '<div class="layui-row"><div class="layui-col-md9"><label style="color: blue;">' + mapCharacter.name + '</label><label> - 等级:' + mapCharacter.level + '</label></div><div class="layui-col-md3"><button type="button" style="height:14px;line-height: 14px;">私聊</button></div></div>';
206             $('#online-all').append(row);
207             $('#online-player').append(row);
208         }
209 
210         for (let index in mapMobList) {
211             let mapMob = mapMobList[index];
212             let row = '<div class="layui-row"><div class="layui-col-md9"><label style="color: red;">' + mapMob.name + '</label><label> - 等级:' + mapMob.level + '</label></div><div class="layui-col-md3"><button type="button" style="height:14px;line-height: 14px;" onclick="wowClient.sendBattleMob(\'' + mapMob.id + '\');">战斗</button><button type="button" style="height:14px;line-height:14px;" onclick="guaji();">挂机</button></div></div>';
213             $('#online-all').append(row);
214             $('#online-mob').append(row);
215         }
216     },
217     // 战斗结算
218     settlement: function (battleResult) {
219         $('.lbl-level').html(battleResult.settleLevel);
220         $('.lbl-exp').html(battleResult.settleExp);
221     },
222     // 休眠
223     sleep: function (milliseconds) {
224         let p = new Promise(function (resolve) {
225             setTimeout(function () {
226                 resolve();
227             }, milliseconds)
228         });
229         return p;
230     },
231     // 关闭
232     close: function () {
233         this.webSocket.close();
234     }
235 };
236 
237 RequestMessage.prototype = {
238     loadCache: function () {
239         this.header.messageCode = MessageCode.LoadCache;
240     },
241     login: function () {
242         this.header.messageCode = MessageCode.Login;
243     },
244     chat: function () {
245         this.header.messageCode = MessageCode.Chat;
246         this.content = {
247             senderId: charId,
248             senderName: charName,
249             receiverId: '',
250             receiverName: '',
251             message: $('#msg').val()
252         };
253     },
254     move: function (mapId) {
255         this.header.messageCode = MessageCode.Move;
256         this.content = {
257             destMapId: mapId
258         };
259     },
260     battleMob: function (mobId) {
261         this.header.messageCode = MessageCode.BattleMob;
262         this.content = {
263             mobId: mobId
264         };
265     },
266     refreshOnline: function () {
267         this.header.messageCode = MessageCode.RefreshOnline;
268     }
269 };
270 
271 // wow客户端
272 window.wowClient = new WowClient();
273 
274 // 关闭窗口
275 window.onbeforeunload = function (event) {
276     wowClient.close();
277 };
278 
279 document.onkeydown = function (event) {
280     let e = event || window.event || arguments.callee.caller.arguments[0];
281     if (e.keyCode === 13 && document.activeElement.id === 'msg') {
282         wowClient.sendChat();
283     }
284 };
Copy the code

main.js

 

summary

This chapter mainly realizes the socket communication logic, the processing of the message involves the game’s business processing logic, only a simple talk about some.

In addition, because the interval is longer, the code cutting workload is larger. This chapter is only a rough cut of the completed code. Some changes to the source code, some of the major ones will be covered in this article, but others will not be covered here.

For some corners of the content, the code will change, but not reflected in the text, if there is a problem, you can leave a message for consultation.

Download source address: 545c.com/file/149603…

In this paper, the original address: www.cnblogs.com/lyosaki88/p…

Project Exchange Group: 329989095