Replace taking over games with forced saves.

Instead of reusing the id, just SIGHUP the game process.  This works
whether it is using polling, WebSockets, or dgamelaunch.
This commit is contained in:
John "Elwin" Edwards 2012-07-15 22:33:44 -07:00
parent a847191450
commit a0be18657b
2 changed files with 84 additions and 5 deletions

View file

@ -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";

View file

@ -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();