+ break;
+ case "disconnect":
+ this.$delete(this.people, data.from);
+ break;
+ case "killed":
+ // I logged in elsewhere:
+ // TODO: this fails. See https://github.com/websockets/ws/issues/489
+ //this.conn.removeEventListener("message", this.socketMessageListener);
+ //this.conn.removeEventListener("close", this.socketCloseListener);
+ //this.conn.close();
+ this.conn = null;
+ alert(this.st.tr["New connexion detected: tab now offline"]);
+ break;
+ case "askidentity": {
+ // Request for identification (TODO: anonymous shouldn't need to reply)
+ const me = {
+ // Decompose to avoid revealing email
+ name: this.st.user.name,
+ sid: this.st.user.sid,
+ id: this.st.user.id
+ };
+ this.send("identity", { data: me, target: data.from });
+ break;
+ }
+ case "identity": {
+ const user = data.data;
+ if (user.name) {
+ // If I multi-connect, kill current connexion if no mark (I'm older)
+ if (
+ this.newConnect[user.sid] &&
+ user.id > 0 &&
+ user.id == this.st.user.id &&
+ user.sid != this.st.user.sid
+ ) {
+ if (!this.killed[this.st.user.sid]) {
+ this.send("killme", { sid: this.st.user.sid });
+ this.killed[this.st.user.sid] = true;
+ }
+ }
+ if (user.sid != this.st.user.sid) {
+ //I already know my identity...
+ this.$set(this.people, user.sid, {
+ id: user.id,
+ name: user.name
+ });
+ }
+ }
+ delete this.newConnect[user.sid];
+ break;
+ }
+ case "askgame":
+ // Send current (live) game if not asked by any of the players
+ if (
+ this.game.type == "live" &&
+ this.game.players.every(p => p.sid != data.from[0])
+ ) {
+ const myGame = {
+ id: this.game.id,
+ fen: this.game.fen,
+ players: this.game.players,
+ vid: this.game.vid,
+ cadence: this.game.cadence,
+ score: this.game.score,
+ rid: this.st.user.sid //useful in Hall if I'm an observer
+ };
+ this.send("game", { data: myGame, target: data.from });
+ }
+ break;
+ case "askfullgame":
+ this.send("fullgame", { data: this.game, target: data.from });
+ break;
+ case "fullgame":
+ // Callback "roomInit" to poll clients only after game is loaded
+ let game = data.data;
+ // Move format isn't the same in storage and in browser,
+ // because of the 'addTime' field.
+ game.moves = game.moves.map(m => { return m.move || m; });
+ this.loadGame(game, this.roomInit);
+ break;
+ case "asklastate":
+ // Sending last state if I played a move or score != "*"
+ if (
+ (this.game.moves.length > 0 && this.vr.turn != this.game.mycolor) ||
+ this.game.score != "*" ||
+ this.drawOffer == "sent"
+ ) {
+ // Send our "last state" informations to opponent
+ const L = this.game.moves.length;
+ const myIdx = ["w", "b"].indexOf(this.game.mycolor);
+ const myLastate = {
+ // NOTE: lastMove (when defined) includes addTime
+ lastMove: L > 0 ? this.game.moves[L - 1] : undefined,
+ // Since we played a move (or abort or resign),
+ // only drawOffer=="sent" is possible
+ drawSent: this.drawOffer == "sent",
+ score: this.game.score,