diff --git a/.gitignore b/.gitignore index bc67cdb..1f7b4c7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ node_modules trash .DS_Store *.sublime-* -yarn.lock \ No newline at end of file +yarn.lock +.idea/ +.vscode/ diff --git a/Client.js b/Client.js index bbac066..8bef945 100644 --- a/Client.js +++ b/Client.js @@ -6,7 +6,7 @@ function Client (manager,socket) { this.room = null; this.cfg = null; this.nickname = ''; - this.id = Math.random(); + this.id = getRandomString(); // length: 64 // this.ip = ''; this.onSocketUpdate = null; diff --git a/Game.js b/Game.js index 98b2747..a08e742 100644 --- a/Game.js +++ b/Game.js @@ -1124,4 +1124,14 @@ Game.prototype.getLiveMessagePacks = function () { return this.hostPlayer.messagePacks; }; +Game.prototype.getMessagePacks = function(target) { + if (target === 'host') { + return this.hostPlayer.messagePacks; + } else if (target === 'guest') { + return this.guestPlayer.messagePacks; + } else { + return null; + } +}; + global.Game = Game; \ No newline at end of file diff --git a/RoomManager.js b/RoomManager.js index de6eee2..0cf2159 100644 --- a/RoomManager.js +++ b/RoomManager.js @@ -22,31 +22,25 @@ function RoomManager (cfg) { setInterval(this.cleanUp.bind(this),60*1000); } -RoomManager.prototype.createClient = function (socket,id) { +RoomManager.prototype.createClient = function (socket,id,reconnect) { if (this.clients.length >= this.MAX_CLIENTS) { socket.disconnect(); return; } var client; - if (id) { - var room; - for (var i = 0; i < this.rooms.length; i++) { - room = this.rooms[i]; - // if (!room.reconnecting) continue; // 服务器可能还不知道掉线,所以注释掉. - // console.log('host:%s\nguest:%s\nyou:%s',room.host.id,room.guest.id,id); + var room; + if (id && reconnect) { + // 在游戏中掉线的用户,updateSocket后即可恢复连接 + if (this.checkInRoom(id)) { + room = this.getRoomByClientId(id); if (room.host.id === id) { client = room.host; client.updateSocket(socket); - break; - } - if (room.guest && room.guest.id === id) { + } else { client = room.guest; client.updateSocket(socket); - break; } - } - if (client) { room.reconnecting = false; socket.emit('game reconnect'); room.emit('opponent reconnect'); @@ -54,6 +48,16 @@ RoomManager.prototype.createClient = function (socket,id) { socket.emit('game reconnect failed'); } } + + if (id && !reconnect) { + // 掉线并刷新了浏览器的用户,不建立Client对象 + // 首先,服务器发送重建对战需要的数据 + this.sendReconnectContent(socket,id); + // 等待客户端重建现场,进行updateSocket + socket.on('updateSocket',this.updateSocket.bind(this,socket,id)); + return; + } + if (!client) { client = new Client(this,socket); } @@ -63,7 +67,15 @@ RoomManager.prototype.createClient = function (socket,id) { // this.maxClientsCount = this.clients.length; // console.log(new Date().toISOString().replace('T',' ').substr(0,19)+' Max clients count: %s',this.clients.length); // } + + this.bindSocketEvent(socket, client); + // socket.on('reloadCardInfo',this.reloadCardInfo.bind(this)); + + socket.emit('version',this.VERSION); + this.updateRoomList(); +}; +RoomManager.prototype.bindSocketEvent = function (socket, client) { socket.on('error',this.handleError.bind(this,client)); socket.on('disconnect',this.disconnect.bind(this,client)); socket.on('createRoom',this.createRoom.bind(this,client)); @@ -83,12 +95,74 @@ RoomManager.prototype.createClient = function (socket,id) { socket.on('surrender',client.surrender.bind(client)); socket.on('drop',client.drop.bind(client)); socket.on('tick',client.tick.bind(client)); +} - // socket.on('reloadCardInfo',this.reloadCardInfo.bind(this)); +RoomManager.prototype.checkInRoom = function (id) { + var room; + for (var i = 0; i < this.rooms.length; i++) { + room = this.rooms[i]; + if ((room.host.id === id) || (room.guest && room.guest.id === id)) { + return true; + } + } + return false; +} - socket.emit('version',this.VERSION); - this.updateRoomList(); -}; +RoomManager.prototype.getRoomByClientId = function (id) { + var room; + for (var i = 0; i < this.rooms.length; i++) { + room = this.rooms[i]; + if ((room.host.id === id) || (room.guest.id === id)) { + return room; + } + } + return null; +} + +RoomManager.prototype.sendReconnectContent = function (socket, id) { + // 发送该玩家的游戏录像,等待客户端恢复对战 + var room; + var position; + if (this.checkInRoom(id)) { + room = this.getRoomByClientId(id); + if (room.host.id === id) { + position = 'host'; + } else { + position = 'guest'; + } + socket.emit('reconnectContent', { + 'position': position, + 'messagePacks': room.game.getMessagePacks(position) + }); + } else { + socket.emit('game reconnect failed'); + } +} + +RoomManager.prototype.updateSocket = function (socket, id) { + // 获知客户端恢复对战现场后,updateSocket + var room; + var client; + if (this.checkInRoom(id)) { + room = this.getRoomByClientId(id); + if (room.host.id === id) { + client = room.host; + } else { + client = room.guest; + } + client.updateSocket(socket); + this.bindSocketEvent(socket,client); + this.clients.push(client); + + client.emit('tock'); + client.emit('version',this.VERSION); + + room.reconnecting = false; + room.emit('opponent reconnect'); + } else { + client.emit('game reconnect failed'); + } +} RoomManager.prototype.handleError = function (client,err) { console.error(err); diff --git a/test.js b/test.js index a409a07..989c1ac 100644 --- a/test.js +++ b/test.js @@ -1,5 +1,21 @@ 'use strict'; +// return hex string of a random 256bit number +global.getRandomString = function () { + if (global.window) { + var array = new Uint32Array(8); + window.crypto.getRandomValues(array); + return array.reduce(function(str, num){ + console.log(num.toString(16).length) + return str+('0000000' + num.toString(16)).slice(-8); + }, '') + } else { + var crypto = require('crypto'); + var numString = crypto.randomBytes(32).toString('hex'); + return ('0'.repeat(63) + numString).slice(-64); + } +} + if (!global.window) { global.Random = require("random-js"); require("./util.js"); @@ -157,8 +173,7 @@ io.on('connect',function (socket) { var query = require('url').parse(req.url,true).query; // console.log('connect: %s, count: %s',req.connection.remoteAddress,getSocketCount()); // console.log(query.clientId); - roomManager.createClient(socket,+query.clientId); - + roomManager.createClient(socket,query.clientId,query.reconnect); // test // socket.on('force disconnect',function () { // socket.disconnect(); diff --git a/webxoss-client b/webxoss-client index 6d358bd..09e0115 160000 --- a/webxoss-client +++ b/webxoss-client @@ -1 +1 @@ -Subproject commit 6d358bdb59d985d7482cd6fba12c8935dab9090d +Subproject commit 09e011562ace5b5944d386e207dfc439c1220f1e