comparison rlgterm.js @ 59:00b985b8ba6a

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.
author John "Elwin" Edwards <elwin@sdf.org>
date Tue, 19 Jun 2012 16:19:50 -0700
parents 7a50b4412fea
children 071ec6b1ec03
comparison
equal deleted inserted replaced
58:7a50b4412fea 59:00b985b8ba6a
66 "name": "Super-Rogue", 66 "name": "Super-Rogue",
67 "uname": "srogue" 67 "uname": "srogue"
68 } 68 }
69 }; 69 };
70 70
71 /* Login name and key */ 71 var session = {
72 var lname = null; 72 /* The session id assigned by the server. */
73 var lcred = null; 73 id: null,
74 /* The session id assigned by the server. */ 74 /* Login name and key */
75 var sessid = null; 75 lname: null,
76 lcred: null,
77 /* Whether the game is being played or just watched. */
78 playing: false
79 };
76 80
77 function writeData(hexstr) { 81 function writeData(hexstr) {
78 var codenum; 82 var codenum;
79 var codes = []; 83 var codes = [];
80 var nc; 84 var nc;
211 } 215 }
212 return havedata; 216 return havedata;
213 } 217 }
214 218
215 function getData() { 219 function getData() {
216 if (sessid == null) 220 if (session.id == null)
217 return; 221 return;
218 var datareq = new XMLHttpRequest(); 222 var datareq = new XMLHttpRequest();
219 var msg = JSON.stringify({"id": sessid, "t": "n"}); 223 var msg = JSON.stringify({"id": session.id, "t": "n"});
220 datareq.onreadystatechange = function () { 224 datareq.onreadystatechange = function () {
221 if (datareq.readyState == 4 && datareq.status == 200) { 225 if (datareq.readyState == 4 && datareq.status == 200) {
222 var wasdata = processMsg(datareq.responseText); 226 var wasdata = processMsg(datareq.responseText);
223 if (wasdata != null) { 227 if (wasdata != null) {
224 if (wasdata) 228 if (wasdata)
243 } 247 }
244 } 248 }
245 249
246 function sendback(str) { 250 function sendback(str) {
247 /* For responding to terminal queries. */ 251 /* For responding to terminal queries. */
248 var msgDict = {"id": sessid, "t": "d", "n": nsend++, "d": str}; 252 var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": str};
249 var datareq = new XMLHttpRequest(); 253 var datareq = new XMLHttpRequest();
250 datareq.onreadystatechange = postResponseHandler; 254 datareq.onreadystatechange = postResponseHandler;
251 datareq.open('POST', '/feed', true); 255 datareq.open('POST', '/feed', true);
252 datareq.send(JSON.stringify(msgDict)); 256 datareq.send(JSON.stringify(msgDict));
253 return; 257 return;
254 } 258 }
255 259
256 function sendkey(ev) { 260 function sendkey(ev) {
257 if (sessid == null) 261 if (!session.playing)
258 return; 262 return;
259 var keynum = ev.keyCode; 263 var keynum = ev.keyCode;
260 var code; 264 var code;
261 if (keynum >= ev.DOM_VK_A && keynum <= ev.DOM_VK_Z) { 265 if (keynum >= ev.DOM_VK_A && keynum <= ev.DOM_VK_Z) {
262 /* Letters. This assumes the codes are 65-90. */ 266 /* Letters. This assumes the codes are 65-90. */
289 } 293 }
290 else { 294 else {
291 debug(1, "Ignoring keycode " + keynum); 295 debug(1, "Ignoring keycode " + keynum);
292 return; 296 return;
293 } 297 }
294 // Isn't this check redundant? 298 ev.preventDefault();
295 if (sessid != null)
296 ev.preventDefault();
297 var datareq = new XMLHttpRequest(); 299 var datareq = new XMLHttpRequest();
298 var msgDict = {"id": sessid, "t": "d", "n": nsend++, "d": code}; 300 var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": code};
299 datareq.onreadystatechange = postResponseHandler; 301 datareq.onreadystatechange = postResponseHandler;
300 datareq.open('POST', '/feed', true); 302 datareq.open('POST', '/feed', true);
301 datareq.send(JSON.stringify(msgDict)); 303 datareq.send(JSON.stringify(msgDict));
302 return; 304 return;
303 } 305 }
305 var charshifts = { '-': "5f", '=': "2b", '[': "7b", ']': "7d", '\\': "7c", 307 var charshifts = { '-': "5f", '=': "2b", '[': "7b", ']': "7d", '\\': "7c",
306 ';': "3a", '\'': "22", ',': "3c", '.': "3e", '/': "3f", '`': "7e" 308 ';': "3a", '\'': "22", ',': "3c", '.': "3e", '/': "3f", '`': "7e"
307 } 309 }
308 310
309 function vkey(c) { 311 function vkey(c) {
310 if (sessid == null) 312 if (!session.playing)
311 return; 313 return;
312 var keystr; 314 var keystr;
313 if (c.match(/^[a-z]$/)) { 315 if (c.match(/^[a-z]$/)) {
314 if (termemu.ctrlp()) { 316 if (termemu.ctrlp()) {
315 var n = c.charCodeAt(0) - 96; 317 var n = c.charCodeAt(0) - 96;
343 keystr = c.charCodeAt(0).toString(16); 345 keystr = c.charCodeAt(0).toString(16);
344 } 346 }
345 else 347 else
346 return; 348 return;
347 var datareq = new XMLHttpRequest(); 349 var datareq = new XMLHttpRequest();
348 var msgDict = {"id": sessid, "t": "d", "n": nsend++, "d": keystr}; 350 var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": keystr};
349 datareq.onreadystatechange = postResponseHandler; 351 datareq.onreadystatechange = postResponseHandler;
350 datareq.open('POST', '/feed', true); 352 datareq.open('POST', '/feed', true);
351 datareq.send(JSON.stringify(msgDict)); 353 datareq.send(JSON.stringify(msgDict));
352 return; 354 return;
353 } 355 }
380 return; 382 return;
381 } 383 }
382 384
383 function formlogin(ev) { 385 function formlogin(ev) {
384 ev.preventDefault(); 386 ev.preventDefault();
385 if (sessid != null) 387 if (session.id != null)
386 return; 388 return;
387 var loginmsg = {}; 389 var loginmsg = {};
388 loginmsg["name"] = document.getElementById("input_name").value; 390 loginmsg["name"] = document.getElementById("input_name").value;
389 loginmsg["pw"] = document.getElementById("input_pw").value; 391 loginmsg["pw"] = document.getElementById("input_pw").value;
390 var req = new XMLHttpRequest(); 392 var req = new XMLHttpRequest();
392 if (req.readyState != 4 || req.status != 200) 394 if (req.readyState != 4 || req.status != 200)
393 return; 395 return;
394 var reply = JSON.parse(req.responseText); 396 var reply = JSON.parse(req.responseText);
395 if (reply.t == 'l') { 397 if (reply.t == 'l') {
396 /* Success */ 398 /* Success */
397 lcred = reply.k; 399 session.lcred = reply.k;
398 lname = reply.u; 400 session.lname = reply.u;
399 setTitle("Logged in as " + reply.u); 401 setTitle("Logged in as " + reply.u);
400 debug(1, "Logged in as " + reply.u + " with id " + reply.k); 402 debug(1, "Logged in as " + reply.u + " with id " + reply.k);
401 setmode("choose"); 403 setmode("choose");
402 } 404 }
403 else if (reply.t == 'E') { 405 else if (reply.t == 'E') {
410 req.send(JSON.stringify(loginmsg)); 412 req.send(JSON.stringify(loginmsg));
411 return; 413 return;
412 } 414 }
413 415
414 function getcurrent() { 416 function getcurrent() {
415 if (sessid) 417 if (session.id)
416 return; 418 return;
417 var req = new XMLHttpRequest(); 419 var req = new XMLHttpRequest();
418 req.onreadystatechange = function () { 420 req.onreadystatechange = function () {
419 if (req.readyState != 4 || req.status != 200) 421 if (req.readyState != 4 || req.status != 200)
420 return; 422 return;
428 if (!reply.s) { 430 if (!reply.s) {
429 return; 431 return;
430 } 432 }
431 var gamediv = document.getElementById("gametable"); 433 var gamediv = document.getElementById("gametable");
432 while (gamediv.children.length > 2) 434 while (gamediv.children.length > 2)
433 gamediv.removeChild(optdiv.children[2]); 435 gamediv.removeChild(gamediv.children[2]);
434 if (reply.g.length === 0) { 436 if (reply.g.length === 0) {
435 gamediv.style.display = "none"; 437 gamediv.style.display = "none";
436 document.getElementById("nogames").style.display = "block"; 438 document.getElementById("nogames").style.display = "block";
437 } 439 }
438 else { 440 else {
441 } 443 }
442 for (var i = 0; i < reply.g.length; i++) { 444 for (var i = 0; i < reply.g.length; i++) {
443 var row = document.createElement("div"); 445 var row = document.createElement("div");
444 var cell1 = document.createElement("div"); 446 var cell1 = document.createElement("div");
445 var cell2 = document.createElement("div"); 447 var cell2 = document.createElement("div");
448 var cell3 = document.createElement("div");
446 cell1.appendChild(document.createTextNode(reply.g[i].p)); 449 cell1.appendChild(document.createTextNode(reply.g[i].p));
447 cell2.appendChild(document.createTextNode(reply.g[i].g)); 450 cell2.appendChild(document.createTextNode(reply.g[i].g));
451 var button = document.createElement("span");
452 button.appendChild(document.createTextNode("Watch"));
453 button.onclick = makeWatcher(reply.g[i].n);
454 button.className = "ibutton";
455 cell3.appendChild(button);
448 row.appendChild(cell1); 456 row.appendChild(cell1);
449 row.appendChild(cell2); 457 row.appendChild(cell2);
458 row.appendChild(cell3);
450 gamediv.appendChild(row); 459 gamediv.appendChild(row);
451 } 460 }
452 }; 461 };
453 req.open('GET', '/status', true); 462 req.open('GET', '/status', true);
454 req.send(); 463 req.send();
455 return; 464 return;
456 } 465 }
457 466
458 function getchoices() { 467 function getchoices() {
459 if (sessid != null || !lcred) 468 if (session.id != null || !session.lcred)
460 return; 469 return;
461 var req = new XMLHttpRequest(); 470 var req = new XMLHttpRequest();
462 req.onreadystatechange = function () { 471 req.onreadystatechange = function () {
463 if (req.readyState != 4 || req.status != 200) 472 if (req.readyState != 4 || req.status != 200)
464 return; 473 return;
467 reply = JSON.parse(req.responseText); 476 reply = JSON.parse(req.responseText);
468 } catch (e) { 477 } catch (e) {
469 if (e instanceof SyntaxError) 478 if (e instanceof SyntaxError)
470 return; 479 return;
471 } 480 }
472 if (!("name" in reply) || reply["name"] != lname || !("stat" in reply)) 481 if (!("name" in reply) || reply["name"] != session.lname ||
482 !("stat" in reply))
473 return; 483 return;
474 var optdiv = document.getElementById("opttable"); 484 var optdiv = document.getElementById("opttable");
475 /* Don't remove the first child, it's the header. */ 485 /* Don't remove the first child, it's the header. */
476 while (optdiv.childNodes.length > 1) 486 while (optdiv.childNodes.length > 1)
477 optdiv.removeChild(optdiv.childNodes[1]); 487 optdiv.removeChild(optdiv.childNodes[1]);
501 rowdiv.appendChild(gamediv); 511 rowdiv.appendChild(gamediv);
502 rowdiv.appendChild(actdiv); 512 rowdiv.appendChild(actdiv);
503 optdiv.appendChild(rowdiv); 513 optdiv.appendChild(rowdiv);
504 } 514 }
505 }; 515 };
506 req.open('GET', '/pstatus/' + lname, true); 516 req.open('GET', '/pstatus/' + session.lname, true);
507 req.send(); 517 req.send();
508 return; 518 return;
509 } 519 }
510 520
511 /* This can't be in the loop in getchoices(), or the closure's scope will 521 /* This can't be in the loop in getchoices(), or the closure's scope will
521 } 531 }
522 return starter; 532 return starter;
523 } 533 }
524 534
525 function startgame(game) { 535 function startgame(game) {
526 if (sessid != null || !lcred) 536 if (session.id != null || !session.lcred)
527 return; 537 return;
528 var smsg = {}; 538 var smsg = {};
529 smsg["key"] = lcred; 539 smsg["key"] = session.lcred;
530 smsg["game"] = game.uname; 540 smsg["game"] = game.uname;
531 smsg["h"] = 24; 541 smsg["h"] = 24;
532 smsg["w"] = 80; 542 smsg["w"] = 80;
533 var req = new XMLHttpRequest(); 543 var req = new XMLHttpRequest();
534 req.onreadystatechange = function () { 544 req.onreadystatechange = function () {
535 if (req.readyState != 4 || req.status != 200) 545 if (req.readyState != 4 || req.status != 200)
536 return; 546 return;
537 var reply = JSON.parse(req.responseText); 547 var reply = JSON.parse(req.responseText);
538 if (reply.t == 's') { 548 if (reply.t == 's') {
539 /* Success */ 549 /* Success */
540 sessid = reply.id; 550 session.id = reply.id;
551 session.playing = true;
541 termemu.resize(reply.h, reply.w); 552 termemu.resize(reply.h, reply.w);
542 setTitle("Playing as " + lname); 553 setTitle("Playing as " + session.lname);
543 debug(1, "Playing with id " + sessid); 554 debug(1, "Playing with id " + session.id);
544 setmode("play"); 555 setmode("play");
545 getData(); 556 getData();
546 } 557 }
547 else if (reply.t == 'E') { 558 else if (reply.t == 'E') {
548 debug(1, "Could not start game: " + reply.s); 559 debug(1, "Could not start game: " + reply.s);
554 req.open('POST', '/play', true); 565 req.open('POST', '/play', true);
555 req.send(JSON.stringify(smsg)); 566 req.send(JSON.stringify(smsg));
556 return; 567 return;
557 } 568 }
558 569
570 function startwatching(gamenumber) {
571 if (session.id != null)
572 return;
573 var wmsg = {"n": Number(gamenumber)};
574 var req = new XMLHttpRequest();
575 req.onreadystatechange = function () {
576 if (req.readyState != 4 || req.status != 200)
577 return;
578 var reply = JSON.parse(req.responseText);
579 if (reply.t == 'w') {
580 /* Success */
581 session.id = reply.id;
582 session.playing = false;
583 termemu.resize(reply.h, reply.w);
584 setTitle("Watching");
585 debug(1, "Watching with id " + session.id);
586 setmode("play");
587 getData();
588 }
589 else if (reply.t == 'E') {
590 debug(1, "Could not watch game " + gamenumber + ": " + reply.s);
591 }
592 };
593 req.open('POST', '/watch', true);
594 req.send(JSON.stringify(wmsg));
595 return;
596 }
597
598 function makeWatcher(n) {
599 function watcher(ev) {
600 startwatching(n);
601 }
602 return watcher;
603 }
604
559 function formreg(ev) { 605 function formreg(ev) {
560 ev.preventDefault(); 606 ev.preventDefault();
561 if (sessid != null) 607 if (session.id != null)
562 return; 608 return;
563 var regmsg = {}; 609 var regmsg = {};
564 regmsg["name"] = document.getElementById("regin_name").value; 610 regmsg["name"] = document.getElementById("regin_name").value;
565 regmsg["pw"] = document.getElementById("regin_pw").value; 611 regmsg["pw"] = document.getElementById("regin_pw").value;
566 regmsg["email"] = document.getElementById("regin_email").value; 612 regmsg["email"] = document.getElementById("regin_email").value;
570 return; 616 return;
571 var reply = JSON.parse(req.responseText); 617 var reply = JSON.parse(req.responseText);
572 if (reply.t == 'r') { 618 if (reply.t == 'r') {
573 /* Success */ 619 /* Success */
574 debug(1, "Registered account: " + reply.d); 620 debug(1, "Registered account: " + reply.d);
575 lcred = reply.k; 621 session.lcred = reply.k;
576 lname = reply.u; 622 session.lname = reply.u;
577 setTitle("Logged in as " + lname); 623 setTitle("Logged in as " + session.lname);
578 debug(1, "Logged in as " + lname + "with id " + lcred); 624 debug(1, "Logged in as " + session.lname + "with id " + session.lcred);
579 setmode("choose"); 625 setmode("choose");
580 } 626 }
581 else if (reply.t == 'E') { 627 else if (reply.t == 'E') {
582 debug(1, "Could not register: " + reply.s); 628 debug(1, "Could not register: " + reply.s);
583 document.getElementById("regin_name").value = ""; 629 document.getElementById("regin_name").value = "";
589 req.send(JSON.stringify(regmsg)); 635 req.send(JSON.stringify(regmsg));
590 return; 636 return;
591 } 637 }
592 638
593 function gameover() { 639 function gameover() {
594 if (sessid == null) 640 if (session.id == null)
595 return; 641 return;
596 /* TODO IFACE2 If the end was unexpected, tell player the game was saved. */ 642 /* TODO IFACE2 If the end was unexpected, tell player the game was saved. */
597 sessid = null; 643 session.id = null;
644 session.playing = false;
598 ajaxstate.clear(); 645 ajaxstate.clear();
599 setTitle("Game over."); 646 setTitle("Game over.");
600 nsend = 0; 647 nsend = 0;
601 nrecv = 0; 648 nrecv = 0;
602 msgQ = []; 649 msgQ = [];
603 setmode("choose"); 650 if (session.lcred != null)
651 setmode("choose");
652 else
653 setmode("login");
604 return; 654 return;
605 } 655 }
606 656
607 function logout() { 657 function logout() {
608 lcred = null; 658 session.lcred = null;