Allow resuming computer games, attempt to fix 'ghost move bug'
[vchess.git] / sockets.js
CommitLineData
a29d9d6b 1const url = require('url');
da06a6eb
BA
2const sqlite3 = require('sqlite3');
3const db = new sqlite3.Database('db/vchess.sqlite');
1d184b4c 4
1d184b4c 5module.exports = function(wss) {
da06a6eb
BA
6 db.serialize(function() {
7 db.all("SELECT * FROM Variants", (err,variants) => {
8 let clients = { "index": {} };
9 let games = {}; //pending games (player sid)
10 for (const v of variants)
11 clients[v.name] = {};
12 // No-op function as a callback when sending messages
13 const noop = () => { };
14 wss.on("connection", (socket, req) => {
15 const params = new URL("http://localhost" + req.url).searchParams;
16 const sid = params.get("sid");
17 const page = params.get("page");
18 // Ignore duplicate connections:
19 if (!!clients[page][sid])
1d184b4c 20 {
da06a6eb
BA
21 socket.send(JSON.stringify({code:"duplicate"}));
22 return;
23 }
24 clients[page][sid] = socket;
25 if (page == "index")
26 {
27 // Send counting info
28 const countings = {};
29 for (const v of variants)
30 countings[v.name] = Object.keys(clients[v.name]).length;
31 socket.send(JSON.stringify({code:"counts",counts:countings}));
32 }
33 else
34 {
35 // Send to every client connected on index an update message for counts
36 Object.keys(clients["index"]).forEach( k => {
37 clients["index"][k].send(
38 JSON.stringify({code:"increase",vname:page}), noop);
39 });
40 // Also notify potential opponents:
41 // hit all clients which check if sid corresponds
42 Object.keys(clients[page]).forEach( k => {
43 clients[page][k].send(JSON.stringify({code:"connect",id:sid}), noop);
44 });
45 socket.on("message", objtxt => {
46 let obj = JSON.parse(objtxt);
47 switch (obj.code)
1d184b4c 48 {
3a609580
BA
49 case "newchat":
50 if (!!clients[page][obj.oppid])
51 {
52 clients[page][obj.oppid].send(
53 JSON.stringify({code:"newchat",msg:obj.msg}), noop);
54 }
55 break;
da06a6eb
BA
56 case "newmove":
57 if (!!clients[page][obj.oppid])
58 {
59 clients[page][obj.oppid].send(
60 JSON.stringify({code:"newmove",move:obj.move}), noop);
61 }
62 break;
63 case "ping":
64 if (!!clients[page][obj.oppid])
65 socket.send(JSON.stringify({code:"pong"}));
66 break;
3a609580
BA
67 case "myname":
68 // Reveal my username to opponent
69 if (!!clients[page][obj.oppid])
70 {
71 clients[page][obj.oppid].send(JSON.stringify({
72 code:"oppname", name:obj.name}));
73 }
74 break;
da06a6eb
BA
75 case "lastate":
76 if (!!clients[page][obj.oppid])
77 {
78 const oppId = obj.oppid;
79 obj.oppid = sid; //I'm oppid for my opponent
80 clients[page][oppId].send(JSON.stringify(obj), noop);
81 }
82 break;
83 case "newgame":
84 if (!!games[page])
85 {
86 // Start a new game
87 const oppId = games[page]["id"];
88 const fen = games[page]["fen"];
89 delete games[page];
90 const mycolor = Math.random() < 0.5 ? 'w' : 'b';
91 socket.send(JSON.stringify(
92 {code:"newgame",fen:fen,oppid:oppId,color:mycolor}));
93 if (!!clients[page][oppId])
94 {
95 clients[page][oppId].send(
96 JSON.stringify(
97 {code:"newgame",fen:fen,oppid:sid,color:mycolor=="w"?"b":"w"}),
98 noop);
99 }
100 }
101 else
102 games[page] = {id:sid, fen:obj.fen}; //wait for opponent
103 break;
104 case "cancelnewgame": //if a user cancel his seek
105 delete games[page];
106 break;
107 case "resign":
108 if (!!clients[page][obj.oppid])
109 clients[page][obj.oppid].send(JSON.stringify({code:"resign"}), noop);
110 break;
1d184b4c 111 }
da06a6eb 112 });
1d184b4c 113 }
da06a6eb
BA
114 socket.on("close", () => {
115 delete clients[page][sid];
116 // Remove potential pending game
117 if (!!games[page] && games[page]["id"] == sid)
118 delete games[page];
119 if (page != "index")
120 {
121 // Send to every client connected on index an update message for counts
122 Object.keys(clients["index"]).forEach( k => {
123 clients["index"][k].send(
124 JSON.stringify({code:"decrease",vname:page}), noop);
125 });
126 }
127 // Also notify potential opponents:
128 // hit all clients which check if sid corresponds
129 Object.keys(clients[page]).forEach( k => {
130 clients[page][k].send(JSON.stringify({code:"disconnect",id:sid}), noop);
131 });
1d184b4c 132 });
1d184b4c
BA
133 });
134 });
135 });
136}