Mercurial > hg > rlgwebd
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; |