RLG-Web client: implement watching.

It is now possible to watch games currently being played through
RLG-Web, but not dgamelaunch.  Also, there are some deficiencies, like
getting chaos until an absolute cursor addressing happens.
This commit is contained in:
John "Elwin" Edwards 2012-06-19 16:19:50 -07:00
parent 553f07360c
commit 67f187700c
2 changed files with 91 additions and 41 deletions

View file

@ -88,7 +88,7 @@
<div class="modal" id="current"> <div class="modal" id="current">
<div id="gametable" class="formtable"> <div id="gametable" class="formtable">
<div class="tcapt">Games in Progress</div> <div class="tcapt">Games in Progress</div>
<div><div>Player</div><div>Game</div></div> <div><div>Player</div><div>Game</div><div>Actions</div></div>
</div> </div>
<div id="nogames">There are no games to watch.</div> <div id="nogames">There are no games to watch.</div>
</div> </div>

View file

@ -68,11 +68,15 @@ var games = {
} }
}; };
/* Login name and key */ var session = {
var lname = null; /* The session id assigned by the server. */
var lcred = null; id: null,
/* The session id assigned by the server. */ /* Login name and key */
var sessid = null; lname: null,
lcred: null,
/* Whether the game is being played or just watched. */
playing: false
};
function writeData(hexstr) { function writeData(hexstr) {
var codenum; var codenum;
@ -213,10 +217,10 @@ function processMsg(msg) {
} }
function getData() { function getData() {
if (sessid == null) if (session.id == null)
return; return;
var datareq = new XMLHttpRequest(); var datareq = new XMLHttpRequest();
var msg = JSON.stringify({"id": sessid, "t": "n"}); var msg = JSON.stringify({"id": session.id, "t": "n"});
datareq.onreadystatechange = function () { datareq.onreadystatechange = function () {
if (datareq.readyState == 4 && datareq.status == 200) { if (datareq.readyState == 4 && datareq.status == 200) {
var wasdata = processMsg(datareq.responseText); var wasdata = processMsg(datareq.responseText);
@ -245,7 +249,7 @@ function postResponseHandler() {
function sendback(str) { function sendback(str) {
/* For responding to terminal queries. */ /* For responding to terminal queries. */
var msgDict = {"id": sessid, "t": "d", "n": nsend++, "d": str}; var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": str};
var datareq = new XMLHttpRequest(); var datareq = new XMLHttpRequest();
datareq.onreadystatechange = postResponseHandler; datareq.onreadystatechange = postResponseHandler;
datareq.open('POST', '/feed', true); datareq.open('POST', '/feed', true);
@ -254,7 +258,7 @@ function sendback(str) {
} }
function sendkey(ev) { function sendkey(ev) {
if (sessid == null) if (!session.playing)
return; return;
var keynum = ev.keyCode; var keynum = ev.keyCode;
var code; var code;
@ -291,11 +295,9 @@ function sendkey(ev) {
debug(1, "Ignoring keycode " + keynum); debug(1, "Ignoring keycode " + keynum);
return; return;
} }
// Isn't this check redundant? ev.preventDefault();
if (sessid != null)
ev.preventDefault();
var datareq = new XMLHttpRequest(); var datareq = new XMLHttpRequest();
var msgDict = {"id": sessid, "t": "d", "n": nsend++, "d": code}; var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": code};
datareq.onreadystatechange = postResponseHandler; datareq.onreadystatechange = postResponseHandler;
datareq.open('POST', '/feed', true); datareq.open('POST', '/feed', true);
datareq.send(JSON.stringify(msgDict)); datareq.send(JSON.stringify(msgDict));
@ -307,7 +309,7 @@ var charshifts = { '-': "5f", '=': "2b", '[': "7b", ']': "7d", '\\': "7c",
} }
function vkey(c) { function vkey(c) {
if (sessid == null) if (!session.playing)
return; return;
var keystr; var keystr;
if (c.match(/^[a-z]$/)) { if (c.match(/^[a-z]$/)) {
@ -345,7 +347,7 @@ function vkey(c) {
else else
return; return;
var datareq = new XMLHttpRequest(); var datareq = new XMLHttpRequest();
var msgDict = {"id": sessid, "t": "d", "n": nsend++, "d": keystr}; var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": keystr};
datareq.onreadystatechange = postResponseHandler; datareq.onreadystatechange = postResponseHandler;
datareq.open('POST', '/feed', true); datareq.open('POST', '/feed', true);
datareq.send(JSON.stringify(msgDict)); datareq.send(JSON.stringify(msgDict));
@ -382,7 +384,7 @@ function togglectrl() {
function formlogin(ev) { function formlogin(ev) {
ev.preventDefault(); ev.preventDefault();
if (sessid != null) if (session.id != null)
return; return;
var loginmsg = {}; var loginmsg = {};
loginmsg["name"] = document.getElementById("input_name").value; loginmsg["name"] = document.getElementById("input_name").value;
@ -394,8 +396,8 @@ function formlogin(ev) {
var reply = JSON.parse(req.responseText); var reply = JSON.parse(req.responseText);
if (reply.t == 'l') { if (reply.t == 'l') {
/* Success */ /* Success */
lcred = reply.k; session.lcred = reply.k;
lname = reply.u; session.lname = reply.u;
setTitle("Logged in as " + reply.u); setTitle("Logged in as " + reply.u);
debug(1, "Logged in as " + reply.u + " with id " + reply.k); debug(1, "Logged in as " + reply.u + " with id " + reply.k);
setmode("choose"); setmode("choose");
@ -412,7 +414,7 @@ function formlogin(ev) {
} }
function getcurrent() { function getcurrent() {
if (sessid) if (session.id)
return; return;
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
req.onreadystatechange = function () { req.onreadystatechange = function () {
@ -430,7 +432,7 @@ function getcurrent() {
} }
var gamediv = document.getElementById("gametable"); var gamediv = document.getElementById("gametable");
while (gamediv.children.length > 2) while (gamediv.children.length > 2)
gamediv.removeChild(optdiv.children[2]); gamediv.removeChild(gamediv.children[2]);
if (reply.g.length === 0) { if (reply.g.length === 0) {
gamediv.style.display = "none"; gamediv.style.display = "none";
document.getElementById("nogames").style.display = "block"; document.getElementById("nogames").style.display = "block";
@ -443,10 +445,17 @@ function getcurrent() {
var row = document.createElement("div"); var row = document.createElement("div");
var cell1 = document.createElement("div"); var cell1 = document.createElement("div");
var cell2 = document.createElement("div"); var cell2 = document.createElement("div");
var cell3 = document.createElement("div");
cell1.appendChild(document.createTextNode(reply.g[i].p)); cell1.appendChild(document.createTextNode(reply.g[i].p));
cell2.appendChild(document.createTextNode(reply.g[i].g)); cell2.appendChild(document.createTextNode(reply.g[i].g));
var button = document.createElement("span");
button.appendChild(document.createTextNode("Watch"));
button.onclick = makeWatcher(reply.g[i].n);
button.className = "ibutton";
cell3.appendChild(button);
row.appendChild(cell1); row.appendChild(cell1);
row.appendChild(cell2); row.appendChild(cell2);
row.appendChild(cell3);
gamediv.appendChild(row); gamediv.appendChild(row);
} }
}; };
@ -456,7 +465,7 @@ function getcurrent() {
} }
function getchoices() { function getchoices() {
if (sessid != null || !lcred) if (session.id != null || !session.lcred)
return; return;
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
req.onreadystatechange = function () { req.onreadystatechange = function () {
@ -469,7 +478,8 @@ function getchoices() {
if (e instanceof SyntaxError) if (e instanceof SyntaxError)
return; return;
} }
if (!("name" in reply) || reply["name"] != lname || !("stat" in reply)) if (!("name" in reply) || reply["name"] != session.lname ||
!("stat" in reply))
return; return;
var optdiv = document.getElementById("opttable"); var optdiv = document.getElementById("opttable");
/* Don't remove the first child, it's the header. */ /* Don't remove the first child, it's the header. */
@ -503,7 +513,7 @@ function getchoices() {
optdiv.appendChild(rowdiv); optdiv.appendChild(rowdiv);
} }
}; };
req.open('GET', '/pstatus/' + lname, true); req.open('GET', '/pstatus/' + session.lname, true);
req.send(); req.send();
return; return;
} }
@ -523,10 +533,10 @@ function makeStarter(gname) {
} }
function startgame(game) { function startgame(game) {
if (sessid != null || !lcred) if (session.id != null || !session.lcred)
return; return;
var smsg = {}; var smsg = {};
smsg["key"] = lcred; smsg["key"] = session.lcred;
smsg["game"] = game.uname; smsg["game"] = game.uname;
smsg["h"] = 24; smsg["h"] = 24;
smsg["w"] = 80; smsg["w"] = 80;
@ -537,10 +547,11 @@ function startgame(game) {
var reply = JSON.parse(req.responseText); var reply = JSON.parse(req.responseText);
if (reply.t == 's') { if (reply.t == 's') {
/* Success */ /* Success */
sessid = reply.id; session.id = reply.id;
session.playing = true;
termemu.resize(reply.h, reply.w); termemu.resize(reply.h, reply.w);
setTitle("Playing as " + lname); setTitle("Playing as " + session.lname);
debug(1, "Playing with id " + sessid); debug(1, "Playing with id " + session.id);
setmode("play"); setmode("play");
getData(); getData();
} }
@ -556,9 +567,44 @@ function startgame(game) {
return; return;
} }
function startwatching(gamenumber) {
if (session.id != null)
return;
var wmsg = {"n": Number(gamenumber)};
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState != 4 || req.status != 200)
return;
var reply = JSON.parse(req.responseText);
if (reply.t == 'w') {
/* Success */
session.id = reply.id;
session.playing = false;
termemu.resize(reply.h, reply.w);
setTitle("Watching");
debug(1, "Watching with id " + session.id);
setmode("play");
getData();
}
else if (reply.t == 'E') {
debug(1, "Could not watch game " + gamenumber + ": " + reply.s);
}
};
req.open('POST', '/watch', true);
req.send(JSON.stringify(wmsg));
return;
}
function makeWatcher(n) {
function watcher(ev) {
startwatching(n);
}
return watcher;
}
function formreg(ev) { function formreg(ev) {
ev.preventDefault(); ev.preventDefault();
if (sessid != null) if (session.id != null)
return; return;
var regmsg = {}; var regmsg = {};
regmsg["name"] = document.getElementById("regin_name").value; regmsg["name"] = document.getElementById("regin_name").value;
@ -572,10 +618,10 @@ function formreg(ev) {
if (reply.t == 'r') { if (reply.t == 'r') {
/* Success */ /* Success */
debug(1, "Registered account: " + reply.d); debug(1, "Registered account: " + reply.d);
lcred = reply.k; session.lcred = reply.k;
lname = reply.u; session.lname = reply.u;
setTitle("Logged in as " + lname); setTitle("Logged in as " + session.lname);
debug(1, "Logged in as " + lname + "with id " + lcred); debug(1, "Logged in as " + session.lname + "with id " + session.lcred);
setmode("choose"); setmode("choose");
} }
else if (reply.t == 'E') { else if (reply.t == 'E') {
@ -591,27 +637,31 @@ function formreg(ev) {
} }
function gameover() { function gameover() {
if (sessid == null) if (session.id == null)
return; return;
/* TODO IFACE2 If the end was unexpected, tell player the game was saved. */ /* TODO IFACE2 If the end was unexpected, tell player the game was saved. */
sessid = null; session.id = null;
session.playing = false;
ajaxstate.clear(); ajaxstate.clear();
setTitle("Game over."); setTitle("Game over.");
nsend = 0; nsend = 0;
nrecv = 0; nrecv = 0;
msgQ = []; msgQ = [];
setmode("choose"); if (session.lcred != null)
setmode("choose");
else
setmode("login");
return; return;
} }
function logout() { function logout() {
lcred = null; session.lcred = null;
lname = null; session.lname = null;
setmode("login"); setmode("login");
} }
function stop() { function stop() {
if (!sessid) if (!session.id)
return; return;
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
req.onreadystatechange = function () { req.onreadystatechange = function () {
@ -621,7 +671,7 @@ function stop() {
} }
}; };
req.open('POST', '/feed', true); req.open('POST', '/feed', true);
req.send(JSON.stringify({"id": sessid, "t": "q"})); req.send(JSON.stringify({"id": session.id, "t": "q"}));
return; return;
} }