Commit | Line | Data |
---|---|---|
a29d9d6b | 1 | const url = require('url'); |
1d184b4c | 2 | |
2807f530 | 3 | // Node version in Ubuntu 16.04 does not know about URL class |
98db2082 BA |
4 | function getJsonFromUrl(url) |
5 | { | |
5bd05dba BA |
6 | const query = url.substr(2); //starts with "/?" |
7 | let result = {}; | |
8 | query.split("&").forEach((part) => { | |
9 | const item = part.split("="); | |
10 | result[item[0]] = decodeURIComponent(item[1]); | |
11 | }); | |
12 | return result; | |
2807f530 BA |
13 | } |
14 | ||
b644ef7f BA |
15 | // Removal in array of strings (socket IDs) |
16 | function remInArray(arr, item) | |
17 | { | |
5bd05dba BA |
18 | const idx = arr.indexOf(item); |
19 | if (idx >= 0) | |
20 | arr.splice(idx, 1); | |
b644ef7f BA |
21 | } |
22 | ||
b57dbd12 BA |
23 | // TODO: empêcher multi-log du même user (envoyer le user ID + secret en même temps que name et...) |
24 | // --> si secret ne matche pas celui trouvé en DB, stop | |
b644ef7f BA |
25 | // TODO: lorsque challenge accepté, seul le dernier joueur à accepter envoi message "please start game" |
26 | // avec les coordonnées des participants. Le serveur renvoit alors les détails de la partie (couleurs, position) | |
27 | //TODO: programmatic re-navigation on current game if we receive a move and are not there | |
4608eed9 | 28 | |
1d184b4c | 29 | module.exports = function(wss) { |
5bd05dba BA |
30 | let clients = {}; //associative array sid --> socket |
31 | wss.on("connection", (socket, req) => { | |
32 | const query = getJsonFromUrl(req.url); | |
33 | const sid = query["sid"]; | |
052d17ea | 34 | // Ignore duplicate connections (on the same live game that we play): |
5bd05dba BA |
35 | if (!!clients[sid]) |
36 | return socket.send(JSON.stringify({code:"duplicate"})); | |
37 | clients[sid] = socket; | |
38 | // Notify room: | |
5a3da968 BA |
39 | Object.keys(clients).forEach(k => { |
40 | if (k != sid) | |
41 | clients[k].send(JSON.stringify({code:"connect",sid:sid})); | |
42 | }); | |
43 | socket.on("message", objtxt => { | |
5bd05dba | 44 | let obj = JSON.parse(objtxt); |
5a3da968 | 45 | if (!!obj.target && !clients[obj.target]) |
b4d619d1 | 46 | return; //receiver not connected, nothing we can do |
5a3da968 | 47 | //console.log(obj.code); |
5bd05dba BA |
48 | switch (obj.code) |
49 | { | |
81d9ce72 BA |
50 | case "pollclients": |
51 | socket.send(JSON.stringify({code:"pollclients", | |
52 | sockIds:Object.keys(clients).filter(k => k != sid)})); | |
5a3da968 BA |
53 | break; |
54 | case "askidentity": | |
81d9ce72 BA |
55 | clients[obj.target].send( |
56 | JSON.stringify({code:"askidentity",from:sid})); | |
57 | break; | |
dd75774d | 58 | case "askchallenge": |
81d9ce72 | 59 | clients[obj.target].send( |
dd75774d | 60 | JSON.stringify({code:"askchallenge",from:sid})); |
81d9ce72 BA |
61 | break; |
62 | case "askgame": | |
63 | clients[obj.target].send( | |
64 | JSON.stringify({code:"askgame",from:sid})); | |
5a3da968 BA |
65 | break; |
66 | case "identity": | |
81d9ce72 BA |
67 | clients[obj.target].send( |
68 | JSON.stringify({code:"identity",user:obj.user})); | |
4d64881e | 69 | break; |
dd75774d | 70 | case "challenge": |
6855163c | 71 | clients[obj.target].send( |
bb7dd7db BA |
72 | JSON.stringify({code:"challenge", chall:obj.chall, from:sid})); |
73 | break; | |
74 | case "acceptchallenge": | |
75 | clients[obj.target].send( | |
76 | JSON.stringify({code:"acceptchallenge", cid:obj.cid, from:sid})); | |
dd75774d | 77 | break; |
a6bddfc6 BA |
78 | case "withdrawchallenge": |
79 | clients[obj.target].send( | |
80 | JSON.stringify({code:"withdrawchallenge", cid:obj.cid, from:sid})); | |
81 | break; | |
5bd05dba BA |
82 | case "refusechallenge": |
83 | clients[obj.target].send( | |
84 | JSON.stringify({code:"refusechallenge", cid:obj.cid, from:sid})); | |
85 | break; | |
98f48579 BA |
86 | case "deletechallenge": |
87 | clients[obj.target].send( | |
88 | JSON.stringify({code:"deletechallenge", cid:obj.cid, from:sid})); | |
89 | break; | |
a6bddfc6 BA |
90 | case "newgame": |
91 | clients[obj.target].send(JSON.stringify( | |
5bd05dba | 92 | {code:"newgame", gameInfo:obj.gameInfo, cid:obj.cid})); |
a6bddfc6 | 93 | break; |
dd75774d | 94 | case "game": |
bb7dd7db | 95 | // TODO: relay (live) game to other player |
4d64881e | 96 | break; |
5bd05dba | 97 | case "newchat": |
5a3da968 | 98 | clients[obj.target].send(JSON.stringify({code:"newchat",msg:obj.msg})); |
5bd05dba BA |
99 | break; |
100 | // Transmit chats and moves to current room | |
101 | // TODO: WebRTC instead in this case (most demanding?) | |
102 | case "newmove": | |
5a3da968 | 103 | clients[obj.target].send(JSON.stringify({code:"newmove",move:obj.move})); |
5bd05dba BA |
104 | break; |
105 | // TODO: generalize that for several opponents | |
106 | case "ping": | |
107 | socket.send(JSON.stringify({code:"pong",gameId:obj.gameId})); | |
108 | break; | |
109 | case "lastate": | |
5a3da968 BA |
110 | const oppId = obj.target; |
111 | obj.oppid = sid; //I'm the opponent of my opponent(s) | |
4d64881e | 112 | clients[oppId].send(JSON.stringify(obj)); |
5bd05dba | 113 | break; |
5bd05dba | 114 | case "resign": |
5a3da968 | 115 | clients[obj.target].send(JSON.stringify({code:"resign"})); |
5bd05dba | 116 | break; |
5bd05dba BA |
117 | } |
118 | }); | |
119 | socket.on("close", () => { | |
120 | delete clients[sid]; | |
b4d619d1 BA |
121 | // Notify every other connected client |
122 | Object.keys(clients).forEach( k => { | |
4d64881e | 123 | clients[k].send(JSON.stringify({code:"disconnect",sid:sid})); |
b4d619d1 | 124 | }); |
5bd05dba BA |
125 | }); |
126 | }); | |
1d184b4c | 127 | } |