diff --git a/rlgterm.js b/rlgterm.js index f3cd783..a462632 100644 --- a/rlgterm.js +++ b/rlgterm.js @@ -622,18 +622,20 @@ function getchoices() { acttext = "Resume your game"; else if (reply.stat[gname] == "0") acttext = "Start a game"; - else if (reply.stat[gname] == "p") - acttext = "Reconnect"; - else if (reply.stat[gname] == "d") - acttext = "Game in progress (dgl)"; + else if (reply.stat[gname] == "p" || reply.stat[gname] == "d") + acttext = "Force save"; else continue; var button = document.createElement("span"); button.appendChild(document.createTextNode(acttext)); - if ("s0p".indexOf(reply.stat[gname]) >= 0) { + if ("s0".indexOf(reply.stat[gname]) >= 0) { button.onclick = makeStarter(gname); button.className = "ibutton"; } + else { + button.onclick = makeStopper(gname); + button.className = "ibutton"; + } var actdiv = document.createElement("div"); actdiv.appendChild(button); var gamediv = document.createElement("div"); @@ -719,6 +721,44 @@ function startgame(game) { return; } +function makeStopper(gname) { + if (!(gname in games)) + return null; + var game = games[gname]; + function stopper(ev) { + stopgame(game); + } + return stopper; +} + +function stopgame(game) { + if (!session.lcred) + return; + var stopmsg = {"key": session.lcred, "g": game.uname}; + var req = new XMLHttpRequest(); + req.onerror = errHandler; + req.onreadystatechange = function () { + if (req.readyState != 4 || req.status != 200) + return; + var reply = JSON.parse(req.responseText); + if (reply.t == 'E') { + if (reply.c == 7) + message("That game has already stopped."); + else if (reply.c == 1) { + logout(); + message("The server forgot about you, please log in again.", "warn"); + } + else { + message("That game could not be stopped because: " + reply.s + + "This might be a bug.", "warn"); + } + } + } + req.open('POST', '/quit', true); + req.send(JSON.stringify(stopmsg)); + return; +} + function wsStart(game) { var sockurl = "ws://" + window.location.host + "/play/" + game.uname; sockurl += "?key=" + session.lcred + "&w=80&h=24"; diff --git a/rlgwebd.js b/rlgwebd.js index 90e2097..fbd6aa0 100755 --- a/rlgwebd.js +++ b/rlgwebd.js @@ -896,6 +896,42 @@ function endgame(client, res) { return; } +/* Stops a running game if the request has the proper key. */ +function stopgame(res, formdata) { + if (!("key" in formdata) || !(formdata["key"] in logins)) { + sendError(res, 1); + return; + } + var pname = logins[formdata["key"]].name; + if (!("g" in formdata) || !(formdata["g"] in games)) { + sendError(res, 2, "No such game."); + return; + } + var gname = formdata["g"]; + function checkback(err, fname) { + if (!fname) { + sendError(res, 7); + return; + } + var fullfile = path.join("/dgldir/inprogress-" + gname, fname); + fs.readFile(fullfile, "utf8", function(err, fdata) { + if (err) { + sendError(res, 7); + return; + } + var pid = parseInt(fdata.split('\n')[0], 10); + process.kill(pid, 'SIGHUP'); + /* The response doesn't mean that the game is gone. The only way + * to make sure a dgamelaunch-supervised game is over would be to + * poll fname until it disappears. */ + res.writeHead(200, {'Content-Type': 'application/json'}); + res.write(JSON.stringify({"t": "q"})); + res.end(); + }); + } + checkprogress(pname, games[gname], checkback, []); +} + function findClient(formdata, playersOnly) { if (typeof(formdata) != "object") return null; @@ -1125,6 +1161,9 @@ function webHandler(req, res) { else if (target == "/watch") { watch(req, res, formdata); } + else if (target == "/quit") { + stopgame(res, formdata); + } else { res.writeHead(405, resheaders); res.end();