2012-05-06 08:45:40 -07:00
|
|
|
/* rlgterm.js: Roguelike Gallery's driver for termemu.js */
|
|
|
|
|
|
|
|
|
|
// A state machine that keeps track of polling the server.
|
|
|
|
|
var ajaxstate = {
|
|
|
|
|
state: 0,
|
|
|
|
|
timerID: null,
|
|
|
|
|
clear: function () {
|
|
|
|
|
if (this.timerID != null) {
|
|
|
|
|
window.clearTimeout(this.timerID);
|
|
|
|
|
this.timerID = null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
set: function (ms) {
|
|
|
|
|
this.clear();
|
|
|
|
|
this.timerID = window.setTimeout(getData, ms);
|
|
|
|
|
},
|
|
|
|
|
gotdata: function () {
|
2012-06-05 22:33:41 -07:00
|
|
|
this.set(1000);
|
|
|
|
|
this.state = 1;
|
2012-05-06 08:45:40 -07:00
|
|
|
},
|
|
|
|
|
gotnothing: function () {
|
|
|
|
|
if (this.state == 0) {
|
2012-06-05 22:33:41 -07:00
|
|
|
this.set(1000);
|
2012-05-06 08:45:40 -07:00
|
|
|
this.state = 1;
|
|
|
|
|
}
|
2012-06-06 10:53:29 -07:00
|
|
|
else if (this.state < 4) {
|
2012-06-05 22:33:41 -07:00
|
|
|
this.set(4000);
|
2012-06-06 10:53:29 -07:00
|
|
|
this.state++;
|
|
|
|
|
}
|
2012-06-20 07:41:59 -07:00
|
|
|
else if (session.playing) {
|
|
|
|
|
if (this.state < 8) {
|
|
|
|
|
this.set(15000);
|
|
|
|
|
this.state++;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* It's been over a minute. Stop polling. */
|
|
|
|
|
this.clear();
|
|
|
|
|
}
|
2012-06-06 10:53:29 -07:00
|
|
|
}
|
|
|
|
|
else {
|
2012-06-20 07:41:59 -07:00
|
|
|
/* If watching, it can't stop polling entirely, because there
|
|
|
|
|
* are no POST events to start it up again. */
|
|
|
|
|
this.set(10000);
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
2012-06-05 22:33:41 -07:00
|
|
|
},
|
|
|
|
|
posted: function (wasdata) {
|
|
|
|
|
if (wasdata) {
|
2012-05-06 08:45:40 -07:00
|
|
|
this.set(1000);
|
2012-06-05 22:33:41 -07:00
|
|
|
this.state = 1;
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
else {
|
2012-06-05 22:33:41 -07:00
|
|
|
this.set(200);
|
|
|
|
|
this.state = 0;
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2012-06-09 14:13:07 -07:00
|
|
|
/* Data on the available games. */
|
|
|
|
|
var games = {
|
|
|
|
|
"rogue3": {
|
|
|
|
|
"name": "Rogue V3",
|
|
|
|
|
"uname": "rogue3"
|
|
|
|
|
},
|
|
|
|
|
"rogue4": {
|
|
|
|
|
"name": "Rogue V4",
|
|
|
|
|
"uname": "rogue4"
|
|
|
|
|
},
|
|
|
|
|
"rogue5": {
|
|
|
|
|
"name": "Rogue V5",
|
|
|
|
|
"uname": "rogue5"
|
|
|
|
|
},
|
|
|
|
|
"srogue": {
|
|
|
|
|
"name": "Super-Rogue",
|
|
|
|
|
"uname": "srogue"
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2012-06-19 16:19:50 -07:00
|
|
|
var session = {
|
|
|
|
|
/* The session id assigned by the server. */
|
|
|
|
|
id: null,
|
|
|
|
|
/* Login name and key */
|
|
|
|
|
lname: null,
|
|
|
|
|
lcred: null,
|
|
|
|
|
/* Whether the game is being played or just watched. */
|
2012-07-12 22:16:15 -07:00
|
|
|
playing: false,
|
|
|
|
|
/* WebSocket for communication */
|
|
|
|
|
sock: null
|
2012-06-19 16:19:50 -07:00
|
|
|
};
|
2012-06-07 15:43:06 -07:00
|
|
|
|
2012-06-21 21:57:04 -07:00
|
|
|
/* The interval ID for checking the status of current games. */
|
|
|
|
|
var statInterval = null;
|
|
|
|
|
/* How frequently to check. */
|
|
|
|
|
var statDelta = 8000;
|
2012-07-14 09:46:26 -07:00
|
|
|
/* A WebSocket to listen for status events. */
|
|
|
|
|
var statsock = null;
|
2012-06-21 21:57:04 -07:00
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
function writeData(hexstr) {
|
|
|
|
|
var codenum;
|
|
|
|
|
var codes = [];
|
|
|
|
|
var nc;
|
|
|
|
|
var u8wait = 0; /* Stores bits from previous bytes of multibyte sequences. */
|
|
|
|
|
var expect = 0; /* The number of 10------ bytes expected. */
|
|
|
|
|
/* UTF-8 translation. */
|
|
|
|
|
for (var i = 0; i < hexstr.length; i += 2) {
|
|
|
|
|
nc = Number("0x" + hexstr.substr(i, 2));
|
|
|
|
|
if (nc < 0x7F) {
|
|
|
|
|
/* 0------- */
|
|
|
|
|
codes.push(nc);
|
|
|
|
|
/* Any incomplete sequence will be discarded. */
|
|
|
|
|
u8wait = 0;
|
|
|
|
|
expect = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (nc < 0xC0) {
|
|
|
|
|
/* 10------ : part of a multibyte sequence */
|
|
|
|
|
if (expect > 0) {
|
|
|
|
|
u8wait <<= 6;
|
|
|
|
|
u8wait += (nc & 0x3F);
|
|
|
|
|
expect--;
|
|
|
|
|
if (expect == 0) {
|
|
|
|
|
codes.push(u8wait);
|
|
|
|
|
u8wait = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Assume an initial byte was missed. */
|
|
|
|
|
u8wait = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* These will all discard any incomplete sequence. */
|
|
|
|
|
else if (nc < 0xE0) {
|
|
|
|
|
/* 110----- : introduces 2-byte sequence */
|
|
|
|
|
u8wait = (nc & 0x1F);
|
|
|
|
|
expect = 1;
|
|
|
|
|
}
|
|
|
|
|
else if (nc < 0xF0) {
|
|
|
|
|
/* 1110---- : introduces 3-byte sequence */
|
|
|
|
|
u8wait = (nc & 0x0F);
|
|
|
|
|
expect = 2;
|
|
|
|
|
}
|
|
|
|
|
else if (nc < 0xF8) {
|
|
|
|
|
/* 11110--- : introduces 4-byte sequence */
|
|
|
|
|
u8wait = (nc & 0x07);
|
|
|
|
|
expect = 3;
|
|
|
|
|
}
|
|
|
|
|
else if (nc < 0xFC) {
|
|
|
|
|
/* 111110-- : introduces 5-byte sequence */
|
|
|
|
|
u8wait = (nc & 0x03);
|
|
|
|
|
expect = 4;
|
|
|
|
|
}
|
|
|
|
|
else if (nc < 0xFE) {
|
|
|
|
|
/* 1111110- : introduces 6-byte sequence */
|
|
|
|
|
u8wait = (nc & 0x01);
|
|
|
|
|
expect = 5;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* 1111111- : should never appear */
|
|
|
|
|
u8wait = 0;
|
|
|
|
|
expect = 0;
|
|
|
|
|
}
|
|
|
|
|
/* Supporting all 31 bits is probably overkill... */
|
|
|
|
|
}
|
|
|
|
|
termemu.write(codes);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-17 09:32:19 -07:00
|
|
|
/* State for sending and receiving messages. */
|
|
|
|
|
var nsend = 0; // The number of the next packet to send.
|
|
|
|
|
var nrecv = 0; // The next packet expected.
|
|
|
|
|
var msgQ = []; // Queue for out-of-order messages.
|
|
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
/* Processes a message from the server, returning true or false if it was a
|
2012-05-17 09:32:19 -07:00
|
|
|
* data message with or without data, null if not data.
|
|
|
|
|
* All non-special responseTexts should be handed directly to this function.
|
|
|
|
|
*/
|
2012-05-06 08:45:40 -07:00
|
|
|
function processMsg(msg) {
|
2012-06-18 13:43:51 -07:00
|
|
|
var msgDicts;
|
2012-05-17 09:32:19 -07:00
|
|
|
var havedata = null; // eventual return value
|
|
|
|
|
try {
|
2012-06-18 13:43:51 -07:00
|
|
|
msgDicts = JSON.parse(msg);
|
2012-05-17 09:32:19 -07:00
|
|
|
} catch (e) {
|
|
|
|
|
if (e instanceof SyntaxError)
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2012-06-18 13:43:51 -07:00
|
|
|
if (msgDicts.length === 0)
|
|
|
|
|
return false;
|
|
|
|
|
for (var j = 0; j < msgDicts.length; j++) {
|
|
|
|
|
if (!msgDicts[j].t)
|
|
|
|
|
continue;
|
|
|
|
|
else if (msgDicts[j].t == "E") {
|
|
|
|
|
if (msgDicts[j].c == 1 || msgDicts[j].c == 6 || msgDicts[j].c == 7) {
|
|
|
|
|
gameover();
|
|
|
|
|
if (msgDicts[j].c == 1) {
|
|
|
|
|
logout();
|
|
|
|
|
}
|
2012-06-09 21:20:14 -07:00
|
|
|
}
|
2012-06-18 13:43:51 -07:00
|
|
|
debug(1, "Server error: " + msgDicts[j].s);
|
2012-05-17 09:32:19 -07:00
|
|
|
}
|
2012-06-18 13:43:51 -07:00
|
|
|
// A data message
|
|
|
|
|
else if (msgDicts[j].t == "d") {
|
|
|
|
|
if (msgDicts[j].n === nrecv) {
|
|
|
|
|
writeData(msgDicts[j].d);
|
2012-05-17 09:32:19 -07:00
|
|
|
nrecv++;
|
2012-06-18 13:43:51 -07:00
|
|
|
/* Process anything in the queue that's now ready. */
|
|
|
|
|
var next;
|
|
|
|
|
while ((next = msgQ.shift()) !== undefined) {
|
|
|
|
|
writeData(next.d);
|
|
|
|
|
nrecv++;
|
|
|
|
|
}
|
2012-05-17 09:32:19 -07:00
|
|
|
}
|
2012-06-18 13:43:51 -07:00
|
|
|
else if (msgDicts[j].n > nrecv) {
|
|
|
|
|
/* The current message comes after one still missing. Queue this one
|
|
|
|
|
* for later use. */
|
|
|
|
|
debug(1, "Got packet " + msgDicts[j].n + ", expected " + nrecv);
|
|
|
|
|
msgQ[msgDicts[j].n - nrecv - 1] = msgDicts[j];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* This message's number was encountered previously. */
|
|
|
|
|
debug(1, "Discarding packet " + msgDicts[j].n + ", expected " + nrecv);
|
|
|
|
|
}
|
|
|
|
|
havedata = true;
|
|
|
|
|
}
|
|
|
|
|
else if (msgDicts[j].t == "T") {
|
|
|
|
|
setTitle(msgDicts[j].d);
|
2012-05-17 09:32:19 -07:00
|
|
|
}
|
2012-06-18 13:43:51 -07:00
|
|
|
else if (msgDicts[j].t == "q") {
|
|
|
|
|
gameover();
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
else {
|
2012-06-18 13:43:51 -07:00
|
|
|
debug(1, "Unrecognized server message " + msg);
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return havedata;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getData() {
|
2012-06-19 16:19:50 -07:00
|
|
|
if (session.id == null)
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
var datareq = new XMLHttpRequest();
|
2012-06-19 16:19:50 -07:00
|
|
|
var msg = JSON.stringify({"id": session.id, "t": "n"});
|
2012-06-21 23:44:51 -07:00
|
|
|
datareq.onerror = errHandler;
|
2012-05-06 08:45:40 -07:00
|
|
|
datareq.onreadystatechange = function () {
|
|
|
|
|
if (datareq.readyState == 4 && datareq.status == 200) {
|
|
|
|
|
var wasdata = processMsg(datareq.responseText);
|
|
|
|
|
if (wasdata != null) {
|
|
|
|
|
if (wasdata)
|
|
|
|
|
ajaxstate.gotdata();
|
|
|
|
|
else
|
|
|
|
|
ajaxstate.gotnothing();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
datareq.open('POST', '/feed', true);
|
2012-05-17 09:32:19 -07:00
|
|
|
datareq.send(msg);
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function postResponseHandler() {
|
|
|
|
|
if (this.readyState == 4 && this.status == 200) {
|
|
|
|
|
// We might want to do something with wasdata someday.
|
|
|
|
|
var wasdata = processMsg(this.responseText);
|
|
|
|
|
ajaxstate.posted();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-21 23:44:51 -07:00
|
|
|
function errHandler() {
|
2012-07-11 11:10:50 -07:00
|
|
|
message("Unable to connect to the server.", "warn");
|
2012-06-21 23:44:51 -07:00
|
|
|
}
|
|
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
function sendback(str) {
|
|
|
|
|
/* For responding to terminal queries. */
|
2012-06-19 16:19:50 -07:00
|
|
|
var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": str};
|
2012-05-06 08:45:40 -07:00
|
|
|
var datareq = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
datareq.onerror = errHandler;
|
2012-05-06 08:45:40 -07:00
|
|
|
datareq.onreadystatechange = postResponseHandler;
|
|
|
|
|
datareq.open('POST', '/feed', true);
|
2012-05-17 09:32:19 -07:00
|
|
|
datareq.send(JSON.stringify(msgDict));
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function sendkey(ev) {
|
2012-06-19 16:19:50 -07:00
|
|
|
if (!session.playing)
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
var keynum = ev.keyCode;
|
|
|
|
|
var code;
|
2012-06-21 09:43:52 -07:00
|
|
|
if (keynum >= 65 && keynum <= 90) {
|
|
|
|
|
/* Letters. */
|
2012-05-06 08:45:40 -07:00
|
|
|
if (ev.ctrlKey)
|
|
|
|
|
keynum -= 64;
|
|
|
|
|
else if (!ev.shiftKey)
|
|
|
|
|
keynum += 32;
|
|
|
|
|
code = keynum.toString(16);
|
|
|
|
|
if (code.length < 2)
|
|
|
|
|
code = "0" + code;
|
|
|
|
|
}
|
2012-06-21 09:43:52 -07:00
|
|
|
else if (keynum >= 48 && keynum <= 57) {
|
2012-05-06 08:45:40 -07:00
|
|
|
/* The number row, NOT the numpad. */
|
|
|
|
|
if (ev.shiftKey) {
|
|
|
|
|
code = numShifts[keynum - 48].toString(16);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
code = keynum.toString(16);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (keynum in keyHexCodes) {
|
|
|
|
|
if (ev.shiftKey)
|
|
|
|
|
code = keyHexCodes[keynum][1];
|
|
|
|
|
else
|
|
|
|
|
code = keyHexCodes[keynum][0];
|
|
|
|
|
}
|
2012-06-21 09:43:52 -07:00
|
|
|
else if (keynum >= 16 && keynum <= 20) {
|
|
|
|
|
/* Shift, Cntl, Alt, CAPSLOCK */
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
debug(1, "Ignoring keycode " + keynum);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-06-19 16:19:50 -07:00
|
|
|
ev.preventDefault();
|
2012-07-15 18:18:53 -07:00
|
|
|
if (session.sock) {
|
|
|
|
|
session.sock.send(JSON.stringify({"t": "d", "d": code}));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var datareq = new XMLHttpRequest();
|
|
|
|
|
var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": code};
|
|
|
|
|
datareq.onerror = errHandler;
|
|
|
|
|
datareq.onreadystatechange = postResponseHandler;
|
|
|
|
|
datareq.open('POST', '/feed', true);
|
|
|
|
|
datareq.send(JSON.stringify(msgDict));
|
|
|
|
|
}
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var charshifts = { '-': "5f", '=': "2b", '[': "7b", ']': "7d", '\\': "7c",
|
|
|
|
|
';': "3a", '\'': "22", ',': "3c", '.': "3e", '/': "3f", '`': "7e"
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-23 17:11:51 -07:00
|
|
|
var kpkeys = { "KP1": "1b4f46", "KP2": "1b4f42", "KP3": "1b5b367e",
|
|
|
|
|
"KP4": "1b4f44", "KP5": "1b5b45", "KP6": "1b4f43",
|
|
|
|
|
"KP7": "1b4f48", "KP8": "1b4f41", "KP9": "1b5b357e" };
|
|
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
function vkey(c) {
|
2012-06-19 16:19:50 -07:00
|
|
|
if (!session.playing)
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
var keystr;
|
|
|
|
|
if (c.match(/^[a-z]$/)) {
|
|
|
|
|
if (termemu.ctrlp()) {
|
|
|
|
|
var n = c.charCodeAt(0) - 96;
|
|
|
|
|
keystr = n.toString(16);
|
|
|
|
|
if (keystr.length < 2)
|
|
|
|
|
keystr = "0" + keystr;
|
|
|
|
|
}
|
|
|
|
|
else if (termemu.shiftp())
|
|
|
|
|
keystr = c.toUpperCase().charCodeAt(0).toString(16);
|
|
|
|
|
else
|
|
|
|
|
keystr = c.charCodeAt(0).toString(16);
|
|
|
|
|
}
|
|
|
|
|
else if (c.match(/^[0-9]$/)) {
|
|
|
|
|
if (termemu.shiftp())
|
|
|
|
|
keystr = numShifts[c.charCodeAt(0) - 48].toString(16);
|
|
|
|
|
else
|
|
|
|
|
keystr = c.charCodeAt(0).toString(16);
|
|
|
|
|
}
|
|
|
|
|
else if (c == '\n')
|
|
|
|
|
keystr = "0a";
|
|
|
|
|
else if (c == '\t')
|
|
|
|
|
keystr = "09";
|
|
|
|
|
else if (c == '\b')
|
|
|
|
|
keystr = "08";
|
|
|
|
|
else if (c == ' ')
|
|
|
|
|
keystr = "20";
|
|
|
|
|
else if (c in charshifts) {
|
|
|
|
|
if (termemu.shiftp())
|
|
|
|
|
keystr = charshifts[c];
|
|
|
|
|
else
|
|
|
|
|
keystr = c.charCodeAt(0).toString(16);
|
|
|
|
|
}
|
2012-06-23 17:11:51 -07:00
|
|
|
else if (c in kpkeys) {
|
|
|
|
|
keystr = kpkeys[c];
|
|
|
|
|
}
|
2012-05-06 08:45:40 -07:00
|
|
|
else
|
|
|
|
|
return;
|
2012-07-15 18:18:53 -07:00
|
|
|
if (session.sock) {
|
|
|
|
|
session.sock.send(JSON.stringify({"t": "d", "d": keystr}));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var datareq = new XMLHttpRequest();
|
|
|
|
|
var msgDict = {"id": session.id, "t": "d", "n": nsend++, "d": keystr};
|
|
|
|
|
datareq.onerror = errHandler;
|
|
|
|
|
datareq.onreadystatechange = postResponseHandler;
|
|
|
|
|
datareq.open('POST', '/feed', true);
|
|
|
|
|
datareq.send(JSON.stringify(msgDict));
|
|
|
|
|
}
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setup() {
|
|
|
|
|
keyHexCodes.init();
|
2012-05-07 11:09:14 -07:00
|
|
|
termemu.init("termwrap", 24, 80);
|
2012-05-22 20:54:33 -07:00
|
|
|
setmode("login");
|
2012-06-23 19:13:34 -07:00
|
|
|
/* Set up the text size. */
|
|
|
|
|
var cssSize = termemu.view.style.fontSize;
|
|
|
|
|
var match = cssSize.match(/\d*/);
|
|
|
|
|
if (!match) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var csize = Number(match[0]);
|
|
|
|
|
var allscreen = document.getElementById("termwrap");
|
|
|
|
|
while (csize > 9 && csize < 48) {
|
|
|
|
|
if (allscreen.scrollWidth * 1.2 > window.innerWidth) {
|
|
|
|
|
csize = textsize(false);
|
|
|
|
|
}
|
|
|
|
|
else if (allscreen.scrollWidth * 2 < window.innerWidth) {
|
|
|
|
|
csize = textsize(true);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-07-15 20:30:33 -07:00
|
|
|
if (!WebSocket) {
|
|
|
|
|
message("Your browser does not support WebSockets. You can still play, " +
|
|
|
|
|
"but it will be slower, and may not work in the future.", "warn");
|
|
|
|
|
}
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toggleshift() {
|
|
|
|
|
termemu.toggleshift();
|
|
|
|
|
keydiv = document.getElementById("shiftkey");
|
|
|
|
|
if (termemu.shiftp())
|
|
|
|
|
keydiv.className = "keysel";
|
|
|
|
|
else
|
|
|
|
|
keydiv.className = "key";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function togglectrl() {
|
|
|
|
|
termemu.togglectrl();
|
|
|
|
|
keydiv = document.getElementById("ctrlkey");
|
|
|
|
|
if (termemu.ctrlp())
|
|
|
|
|
keydiv.className = "keysel";
|
|
|
|
|
else
|
|
|
|
|
keydiv.className = "key";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formlogin(ev) {
|
|
|
|
|
ev.preventDefault();
|
2012-06-19 16:19:50 -07:00
|
|
|
if (session.id != null)
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
2012-05-17 09:32:19 -07:00
|
|
|
var loginmsg = {};
|
|
|
|
|
loginmsg["name"] = document.getElementById("input_name").value;
|
|
|
|
|
loginmsg["pw"] = document.getElementById("input_pw").value;
|
2012-06-07 15:43:06 -07:00
|
|
|
var req = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
req.onerror = errHandler;
|
2012-06-07 15:43:06 -07:00
|
|
|
req.onreadystatechange = function () {
|
|
|
|
|
if (req.readyState != 4 || req.status != 200)
|
|
|
|
|
return;
|
|
|
|
|
var reply = JSON.parse(req.responseText);
|
|
|
|
|
if (reply.t == 'l') {
|
|
|
|
|
/* Success */
|
2012-06-19 16:19:50 -07:00
|
|
|
session.lcred = reply.k;
|
|
|
|
|
session.lname = reply.u;
|
2012-07-10 08:08:54 -07:00
|
|
|
message("You are now logged in as " + reply.u + ".");
|
2012-06-07 15:43:06 -07:00
|
|
|
setmode("choose");
|
|
|
|
|
}
|
|
|
|
|
else if (reply.t == 'E') {
|
2012-07-11 11:10:50 -07:00
|
|
|
var failmsg = "Logging in failed. ";
|
|
|
|
|
if (reply.c == 2)
|
|
|
|
|
failmsg += reply.s.match(/Invalid data: (.*)/)[1];
|
|
|
|
|
else if (reply.c == 3)
|
|
|
|
|
failmsg += "The username or password was incorrect.";
|
|
|
|
|
else if (reply.c == 6)
|
|
|
|
|
failmsg += "The server is shutting down.";
|
|
|
|
|
message(failmsg, "warn");
|
2012-06-07 15:43:06 -07:00
|
|
|
document.getElementById("input_name").value = "";
|
|
|
|
|
document.getElementById("input_pw").value = "";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
req.open('POST', '/login', true);
|
|
|
|
|
req.send(JSON.stringify(loginmsg));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-14 09:46:26 -07:00
|
|
|
function tableCurrent(gamelist) {
|
|
|
|
|
var gamediv = document.getElementById("gametable");
|
|
|
|
|
while (gamediv.children.length > 2)
|
|
|
|
|
gamediv.removeChild(gamediv.children[2]);
|
|
|
|
|
if (gamelist.length === 0) {
|
|
|
|
|
gamediv.style.display = "none";
|
|
|
|
|
document.getElementById("nogames").style.display = "block";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
gamediv.style.display = "table";
|
|
|
|
|
document.getElementById("nogames").style.display = "none";
|
|
|
|
|
}
|
|
|
|
|
for (var i = 0; i < gamelist.length; i++) {
|
|
|
|
|
var row = document.createElement("div");
|
|
|
|
|
var cell1 = document.createElement("div");
|
|
|
|
|
var cell2 = document.createElement("div");
|
|
|
|
|
var cell3 = document.createElement("div");
|
|
|
|
|
var cell4 = document.createElement("div");
|
|
|
|
|
cell1.appendChild(document.createTextNode(gamelist[i].p));
|
|
|
|
|
var uname = gamelist[i].g;
|
|
|
|
|
if (uname in games)
|
|
|
|
|
cell2.appendChild(document.createTextNode(games[uname].name));
|
|
|
|
|
else {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
cell3.appendChild(document.createTextNode(idlestr(gamelist[i].i)));
|
|
|
|
|
var button = document.createElement("span");
|
|
|
|
|
button.appendChild(document.createTextNode("Watch"));
|
|
|
|
|
button.onclick = makeWatcher(gamelist[i].n);
|
|
|
|
|
button.className = "ibutton";
|
|
|
|
|
cell4.appendChild(button);
|
|
|
|
|
row.appendChild(cell1);
|
|
|
|
|
row.appendChild(cell2);
|
|
|
|
|
row.appendChild(cell3);
|
|
|
|
|
row.appendChild(cell4);
|
|
|
|
|
gamediv.appendChild(row);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handles the status socket, opening and closing it when necessary. */
|
|
|
|
|
function wsCurrent() {
|
|
|
|
|
if (!WebSocket)
|
|
|
|
|
return;
|
|
|
|
|
if (session.id) {
|
|
|
|
|
/* Don't bother with status if already playing/watching. */
|
|
|
|
|
if (statsock) {
|
|
|
|
|
statsock.close();
|
|
|
|
|
statsock = null;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-07-16 08:23:51 -07:00
|
|
|
if (session.lcred) {
|
|
|
|
|
/* When starting the socket, the choices list might not be initialized. */
|
|
|
|
|
getchoices();
|
|
|
|
|
}
|
2012-07-14 09:46:26 -07:00
|
|
|
if (statsock)
|
|
|
|
|
return;
|
2012-07-14 10:11:13 -07:00
|
|
|
statsock = new WebSocket("ws://" + window.location.host + "/status");
|
2012-07-14 09:46:26 -07:00
|
|
|
statsock.onmessage = function (ev) {
|
|
|
|
|
var msg;
|
|
|
|
|
try {
|
|
|
|
|
msg = JSON.parse(ev.data);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (e instanceof SyntaxError)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-07-16 08:23:51 -07:00
|
|
|
if (msg.t == "t") {
|
|
|
|
|
tableCurrent(msg.g);
|
|
|
|
|
}
|
|
|
|
|
else if ((msg.t == "b" || msg.t == "e") && msg.p == session.lname) {
|
|
|
|
|
getchoices();
|
2012-07-14 09:46:26 -07:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
statsock.onclose = function (ev) {
|
|
|
|
|
statsock = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-21 21:57:04 -07:00
|
|
|
function getcurrent(clear) {
|
2012-07-16 08:23:51 -07:00
|
|
|
if (WebSocket) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-06-21 21:57:04 -07:00
|
|
|
if (session.id || clear) {
|
|
|
|
|
if (statInterval) {
|
|
|
|
|
window.clearInterval(statInterval);
|
|
|
|
|
statInterval = null;
|
|
|
|
|
}
|
2012-06-18 14:30:05 -07:00
|
|
|
return;
|
2012-06-21 21:57:04 -07:00
|
|
|
}
|
|
|
|
|
if (!statInterval) {
|
|
|
|
|
statInterval = window.setInterval(getcurrent, statDelta);
|
|
|
|
|
}
|
2012-07-14 09:46:26 -07:00
|
|
|
if (session.lcred)
|
|
|
|
|
getchoices();
|
2012-06-18 14:30:05 -07:00
|
|
|
var req = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
req.onerror = errHandler;
|
2012-06-18 14:30:05 -07:00
|
|
|
req.onreadystatechange = function () {
|
|
|
|
|
if (req.readyState != 4 || req.status != 200)
|
|
|
|
|
return;
|
|
|
|
|
var reply;
|
|
|
|
|
try {
|
|
|
|
|
reply = JSON.parse(req.responseText);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (e instanceof SyntaxError)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!reply.s) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-07-14 09:46:26 -07:00
|
|
|
tableCurrent(reply.g);
|
2012-06-18 14:30:05 -07:00
|
|
|
};
|
|
|
|
|
req.open('GET', '/status', true);
|
|
|
|
|
req.send();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-09 14:13:07 -07:00
|
|
|
function getchoices() {
|
2012-06-19 16:19:50 -07:00
|
|
|
if (session.id != null || !session.lcred)
|
2012-06-09 14:13:07 -07:00
|
|
|
return;
|
|
|
|
|
var req = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
req.onerror = errHandler;
|
2012-06-09 14:13:07 -07:00
|
|
|
req.onreadystatechange = function () {
|
|
|
|
|
if (req.readyState != 4 || req.status != 200)
|
|
|
|
|
return;
|
|
|
|
|
var reply;
|
|
|
|
|
try {
|
|
|
|
|
reply = JSON.parse(req.responseText);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (e instanceof SyntaxError)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-06-19 16:19:50 -07:00
|
|
|
if (!("name" in reply) || reply["name"] != session.lname ||
|
|
|
|
|
!("stat" in reply))
|
2012-06-09 14:13:07 -07:00
|
|
|
return;
|
2012-06-09 15:22:56 -07:00
|
|
|
var optdiv = document.getElementById("opttable");
|
|
|
|
|
/* Don't remove the first child, it's the header. */
|
|
|
|
|
while (optdiv.childNodes.length > 1)
|
|
|
|
|
optdiv.removeChild(optdiv.childNodes[1]);
|
2012-06-20 08:49:10 -07:00
|
|
|
for (var gname in games) {
|
|
|
|
|
if (!(gname in reply.stat))
|
2012-06-09 14:13:07 -07:00
|
|
|
continue;
|
2012-06-09 15:22:56 -07:00
|
|
|
var acttext;
|
2012-06-09 14:13:07 -07:00
|
|
|
if (reply.stat[gname] == "s")
|
2012-06-09 15:22:56 -07:00
|
|
|
acttext = "Resume your game";
|
2012-06-09 14:13:07 -07:00
|
|
|
else if (reply.stat[gname] == "0")
|
2012-06-09 15:22:56 -07:00
|
|
|
acttext = "Start a game";
|
2012-07-15 22:33:44 -07:00
|
|
|
else if (reply.stat[gname] == "p" || reply.stat[gname] == "d")
|
|
|
|
|
acttext = "Force save";
|
2012-06-09 14:13:07 -07:00
|
|
|
else
|
|
|
|
|
continue;
|
2012-06-09 15:22:56 -07:00
|
|
|
var button = document.createElement("span");
|
|
|
|
|
button.appendChild(document.createTextNode(acttext));
|
2012-07-15 22:33:44 -07:00
|
|
|
if ("s0".indexOf(reply.stat[gname]) >= 0) {
|
2012-06-09 17:00:25 -07:00
|
|
|
button.onclick = makeStarter(gname);
|
2012-06-11 14:04:35 -07:00
|
|
|
button.className = "ibutton";
|
2012-06-09 17:00:25 -07:00
|
|
|
}
|
2012-07-15 22:33:44 -07:00
|
|
|
else {
|
|
|
|
|
button.onclick = makeStopper(gname);
|
|
|
|
|
button.className = "ibutton";
|
|
|
|
|
}
|
2012-06-09 15:22:56 -07:00
|
|
|
var actdiv = document.createElement("div");
|
|
|
|
|
actdiv.appendChild(button);
|
2012-06-09 14:13:07 -07:00
|
|
|
var gamediv = document.createElement("div");
|
2012-06-09 15:22:56 -07:00
|
|
|
gamediv.appendChild(document.createTextNode(games[gname].name));
|
|
|
|
|
var rowdiv = document.createElement("div");
|
|
|
|
|
rowdiv.appendChild(gamediv);
|
|
|
|
|
rowdiv.appendChild(actdiv);
|
|
|
|
|
optdiv.appendChild(rowdiv);
|
2012-06-09 14:13:07 -07:00
|
|
|
}
|
|
|
|
|
};
|
2012-06-19 16:19:50 -07:00
|
|
|
req.open('GET', '/pstatus/' + session.lname, true);
|
2012-06-09 14:13:07 -07:00
|
|
|
req.send();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-09 17:00:25 -07:00
|
|
|
/* This can't be in the loop in getchoices(), or the closure's scope will
|
|
|
|
|
* get overwritten on the next iteration, and then all the games end up
|
|
|
|
|
* being Super-Rogue.
|
|
|
|
|
*/
|
|
|
|
|
function makeStarter(gname) {
|
|
|
|
|
if (!(gname in games))
|
|
|
|
|
return null;
|
|
|
|
|
var game = games[gname];
|
|
|
|
|
function starter(ev) {
|
|
|
|
|
startgame(game);
|
|
|
|
|
}
|
|
|
|
|
return starter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function startgame(game) {
|
2012-06-19 16:19:50 -07:00
|
|
|
if (session.id != null || !session.lcred)
|
2012-06-07 15:43:06 -07:00
|
|
|
return;
|
2012-07-15 18:18:53 -07:00
|
|
|
if (WebSocket) {
|
|
|
|
|
wsStart(game);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-06-07 15:43:06 -07:00
|
|
|
var smsg = {};
|
2012-06-19 16:19:50 -07:00
|
|
|
smsg["key"] = session.lcred;
|
2012-06-09 17:00:25 -07:00
|
|
|
smsg["game"] = game.uname;
|
2012-06-07 15:43:06 -07:00
|
|
|
smsg["h"] = 24;
|
|
|
|
|
smsg["w"] = 80;
|
2012-05-06 08:45:40 -07:00
|
|
|
var req = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
req.onerror = errHandler;
|
2012-05-06 08:45:40 -07:00
|
|
|
req.onreadystatechange = function () {
|
2012-05-17 09:32:19 -07:00
|
|
|
if (req.readyState != 4 || req.status != 200)
|
|
|
|
|
return;
|
|
|
|
|
var reply = JSON.parse(req.responseText);
|
2012-06-18 13:43:51 -07:00
|
|
|
if (reply.t == 's') {
|
2012-05-17 09:32:19 -07:00
|
|
|
/* Success */
|
2012-06-19 16:19:50 -07:00
|
|
|
session.id = reply.id;
|
|
|
|
|
session.playing = true;
|
2012-05-17 09:32:19 -07:00
|
|
|
termemu.resize(reply.h, reply.w);
|
2012-07-10 16:32:49 -07:00
|
|
|
message("You are now playing " + game.name + ".");
|
2012-05-22 20:54:33 -07:00
|
|
|
setmode("play");
|
2012-05-17 09:32:19 -07:00
|
|
|
getData();
|
|
|
|
|
}
|
|
|
|
|
else if (reply.t == 'E') {
|
2012-06-09 21:20:14 -07:00
|
|
|
if (reply.c == 1) {
|
|
|
|
|
logout();
|
2012-07-11 11:10:50 -07:00
|
|
|
message("The server forgot about you, please log in again.", "warn");
|
2012-07-11 10:30:33 -07:00
|
|
|
}
|
|
|
|
|
else if (reply.c == 4) {
|
2012-07-15 20:30:33 -07:00
|
|
|
if (reply.s == "dgamelaunch") {
|
|
|
|
|
message("You are already playing " + game.name + " over SSH.",
|
|
|
|
|
"warn");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
message("You are already playing " + game.name +
|
|
|
|
|
" in another browser window.", "warn");
|
|
|
|
|
}
|
2012-07-11 10:30:33 -07:00
|
|
|
}
|
|
|
|
|
else if (reply.c == 7) {
|
|
|
|
|
message("The game is being saved, try again in a few seconds.");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
message("The server says it can't start your game because \"" +
|
2012-07-11 11:10:50 -07:00
|
|
|
reply.s + "\". This is probably a bug.", "warn");
|
2012-06-09 21:20:14 -07:00
|
|
|
}
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
};
|
2012-06-07 15:43:06 -07:00
|
|
|
req.open('POST', '/play', true);
|
|
|
|
|
req.send(JSON.stringify(smsg));
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-15 22:33:44 -07:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-15 18:18:53 -07:00
|
|
|
function wsStart(game) {
|
|
|
|
|
var sockurl = "ws://" + window.location.host + "/play/" + game.uname;
|
|
|
|
|
sockurl += "?key=" + session.lcred + "&w=80&h=24";
|
|
|
|
|
ws = new WebSocket(sockurl);
|
|
|
|
|
ws.onopen = function (event) {
|
|
|
|
|
session.id = true;
|
|
|
|
|
session.playing = true;
|
|
|
|
|
session.sock = ws;
|
|
|
|
|
setmode("play");
|
|
|
|
|
};
|
|
|
|
|
ws.onmessage = function (event) {
|
|
|
|
|
var msgObject = JSON.parse(event.data);
|
|
|
|
|
if (msgObject.t == 's') {
|
|
|
|
|
termemu.resize(msgObject.h, msgObject.w);
|
|
|
|
|
message("You are now playing " + msgObject.g + ".");
|
|
|
|
|
}
|
|
|
|
|
else if (msgObject.t == 'd') {
|
|
|
|
|
writeData(msgObject.d);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
ws.onclose = function (event) {
|
|
|
|
|
session.sock = null;
|
|
|
|
|
gameover();
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-19 16:19:50 -07:00
|
|
|
function startwatching(gamenumber) {
|
|
|
|
|
if (session.id != null)
|
|
|
|
|
return;
|
2012-07-12 22:16:15 -07:00
|
|
|
if (WebSocket) {
|
|
|
|
|
wsWatch(gamenumber);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-06-19 16:19:50 -07:00
|
|
|
var wmsg = {"n": Number(gamenumber)};
|
|
|
|
|
var req = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
req.onerror = errHandler;
|
2012-06-19 16:19:50 -07:00
|
|
|
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);
|
2012-06-19 20:08:05 -07:00
|
|
|
termemu.reset();
|
|
|
|
|
termemu.toAltBuf();
|
2012-07-10 16:32:49 -07:00
|
|
|
var pname = reply.p;
|
|
|
|
|
var gname = games[reply.g].name;
|
|
|
|
|
message("You are now watching " + pname + " play " + gname + ".");
|
2012-07-10 13:53:38 -07:00
|
|
|
setmode("watch");
|
2012-06-19 16:19:50 -07:00
|
|
|
getData();
|
|
|
|
|
}
|
|
|
|
|
else if (reply.t == 'E') {
|
2012-07-11 11:10:50 -07:00
|
|
|
message("The game could not be watched: " + reply.s, "warn");
|
2012-06-20 09:12:26 -07:00
|
|
|
getcurrent();
|
2012-06-19 16:19:50 -07:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
req.open('POST', '/watch', true);
|
|
|
|
|
req.send(JSON.stringify(wmsg));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function makeWatcher(n) {
|
|
|
|
|
function watcher(ev) {
|
|
|
|
|
startwatching(n);
|
|
|
|
|
}
|
|
|
|
|
return watcher;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-12 22:16:15 -07:00
|
|
|
function wsWatch(gamenumber) {
|
2012-07-14 10:11:13 -07:00
|
|
|
var sockurl = "ws://" + window.location.host + "/watch/" + String(gamenumber);
|
2012-07-12 22:16:15 -07:00
|
|
|
var ws = new WebSocket(sockurl);
|
|
|
|
|
ws.onopen = function (event) {
|
|
|
|
|
session.id = true;
|
|
|
|
|
session.sock = ws;
|
|
|
|
|
setmode("watch");
|
|
|
|
|
};
|
|
|
|
|
ws.onmessage = function (event) {
|
|
|
|
|
var msgObject = JSON.parse(event.data);
|
2012-07-13 08:39:39 -07:00
|
|
|
if (msgObject.t == 'w') {
|
|
|
|
|
termemu.resize(msgObject.h, msgObject.w);
|
|
|
|
|
termemu.reset();
|
|
|
|
|
termemu.toAltBuf();
|
|
|
|
|
var pname = msgObject.p;
|
|
|
|
|
var gname = games[msgObject.g].name;
|
|
|
|
|
message("You are now watching " + pname + " play " + gname + ".");
|
|
|
|
|
}
|
|
|
|
|
else if (msgObject.t == 'd') {
|
2012-07-12 22:16:15 -07:00
|
|
|
writeData(msgObject.d);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
ws.onclose = function (event) {
|
|
|
|
|
session.sock = null;
|
|
|
|
|
gameover();
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-22 20:54:33 -07:00
|
|
|
function formreg(ev) {
|
|
|
|
|
ev.preventDefault();
|
2012-06-19 16:19:50 -07:00
|
|
|
if (session.id != null)
|
2012-05-22 20:54:33 -07:00
|
|
|
return;
|
|
|
|
|
var regmsg = {};
|
|
|
|
|
regmsg["name"] = document.getElementById("regin_name").value;
|
|
|
|
|
regmsg["pw"] = document.getElementById("regin_pw").value;
|
|
|
|
|
regmsg["email"] = document.getElementById("regin_email").value;
|
|
|
|
|
var req = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
req.onerror = errHandler;
|
2012-05-22 20:54:33 -07:00
|
|
|
req.onreadystatechange = function () {
|
|
|
|
|
if (req.readyState != 4 || req.status != 200)
|
|
|
|
|
return;
|
|
|
|
|
var reply = JSON.parse(req.responseText);
|
|
|
|
|
if (reply.t == 'r') {
|
|
|
|
|
/* Success */
|
2012-07-10 08:08:54 -07:00
|
|
|
message("Welcome " + reply.u + ", you are now registered.");
|
2012-06-19 16:19:50 -07:00
|
|
|
session.lcred = reply.k;
|
|
|
|
|
session.lname = reply.u;
|
2012-07-10 08:08:54 -07:00
|
|
|
message("You are now logged in as " + reply.u + ".");
|
2012-06-07 15:43:06 -07:00
|
|
|
setmode("choose");
|
2012-05-22 20:54:33 -07:00
|
|
|
}
|
|
|
|
|
else if (reply.t == 'E') {
|
2012-07-11 07:37:56 -07:00
|
|
|
var failmsg = "Registration failed.";
|
|
|
|
|
if (reply.c == 2) {
|
|
|
|
|
var errdesc = reply.s.match(/Invalid data: (.*)/)[1];
|
|
|
|
|
if (errdesc.match(/No name/))
|
|
|
|
|
failmsg += " You need to choose a name.";
|
|
|
|
|
else if (errdesc.match(/No password/))
|
|
|
|
|
failmsg += " You need to choose a password.";
|
|
|
|
|
else if (errdesc.match(/Invalid/)) {
|
|
|
|
|
failmsg += " Names must be letters and numbers. E-mail addresses " +
|
|
|
|
|
"can also contain these characters: @.-_";
|
|
|
|
|
}
|
|
|
|
|
else if (errdesc.match(/Username/))
|
|
|
|
|
failmsg += " Someone else is already using that name.";
|
|
|
|
|
else
|
|
|
|
|
failmsg += " This is probably a bug.";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
failmsg += " This is probably a bug.";
|
2012-07-11 11:10:50 -07:00
|
|
|
message(failmsg, "warn");
|
2012-05-22 20:54:33 -07:00
|
|
|
document.getElementById("regin_name").value = "";
|
|
|
|
|
document.getElementById("regin_pw").value = "";
|
|
|
|
|
document.getElementById("regin_email").value = "";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
req.open('POST', '/addacct', true);
|
|
|
|
|
req.send(JSON.stringify(regmsg));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-07 15:43:06 -07:00
|
|
|
function gameover() {
|
2012-06-19 16:19:50 -07:00
|
|
|
if (session.id == null)
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
2012-06-06 10:53:29 -07:00
|
|
|
/* TODO IFACE2 If the end was unexpected, tell player the game was saved. */
|
2012-07-10 13:53:38 -07:00
|
|
|
if (session.playing)
|
|
|
|
|
message("Finished playing.");
|
|
|
|
|
else
|
|
|
|
|
message("Finished watching.");
|
2012-06-19 16:19:50 -07:00
|
|
|
session.id = null;
|
|
|
|
|
session.playing = false;
|
2012-06-06 10:53:29 -07:00
|
|
|
ajaxstate.clear();
|
2012-06-19 20:08:05 -07:00
|
|
|
termemu.toNormBuf();
|
2012-05-17 09:32:19 -07:00
|
|
|
nsend = 0;
|
|
|
|
|
nrecv = 0;
|
|
|
|
|
msgQ = [];
|
2012-06-19 16:19:50 -07:00
|
|
|
if (session.lcred != null)
|
|
|
|
|
setmode("choose");
|
|
|
|
|
else
|
|
|
|
|
setmode("login");
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-09 21:20:14 -07:00
|
|
|
function logout() {
|
2012-06-19 16:19:50 -07:00
|
|
|
session.lcred = null;
|
|
|
|
|
session.lname = null;
|
2012-06-09 21:20:14 -07:00
|
|
|
setmode("login");
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
function stop() {
|
2012-06-19 16:19:50 -07:00
|
|
|
if (!session.id)
|
2012-06-07 15:43:06 -07:00
|
|
|
return;
|
2012-07-12 22:16:15 -07:00
|
|
|
if (session.sock) {
|
|
|
|
|
session.sock.close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-05-06 08:45:40 -07:00
|
|
|
var req = new XMLHttpRequest();
|
2012-06-21 23:44:51 -07:00
|
|
|
req.onerror = errHandler;
|
2012-05-06 08:45:40 -07:00
|
|
|
req.onreadystatechange = function () {
|
|
|
|
|
if (req.readyState == 4 && req.status == 200) {
|
|
|
|
|
processMsg(req.responseText);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
req.open('POST', '/feed', true);
|
2012-06-19 16:19:50 -07:00
|
|
|
req.send(JSON.stringify({"id": session.id, "t": "q"}));
|
2012-05-06 08:45:40 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-22 20:54:33 -07:00
|
|
|
function setmode(mode, ev) {
|
|
|
|
|
if (ev)
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
if (mode == "play") {
|
|
|
|
|
document.getElementById("keyboard").style.display = "block";
|
2012-07-10 13:53:38 -07:00
|
|
|
document.getElementById("playctl").style.display = "block";
|
|
|
|
|
document.getElementById("startgame").style.display = "none";
|
|
|
|
|
document.getElementById("login").style.display = "none";
|
|
|
|
|
document.getElementById("register").style.display = "none";
|
|
|
|
|
document.getElementById("current").style.display = "none";
|
|
|
|
|
}
|
|
|
|
|
else if (mode == "watch") {
|
|
|
|
|
document.getElementById("keyboard").style.display = "none";
|
|
|
|
|
document.getElementById("playctl").style.display = "block";
|
2012-06-07 15:43:06 -07:00
|
|
|
document.getElementById("startgame").style.display = "none";
|
|
|
|
|
document.getElementById("login").style.display = "none";
|
|
|
|
|
document.getElementById("register").style.display = "none";
|
2012-06-18 14:30:05 -07:00
|
|
|
document.getElementById("current").style.display = "none";
|
2012-06-07 15:43:06 -07:00
|
|
|
}
|
2012-07-10 13:53:38 -07:00
|
|
|
else if (mode == "choose") {
|
2012-06-07 15:43:06 -07:00
|
|
|
document.getElementById("keyboard").style.display = "none";
|
2012-07-10 13:53:38 -07:00
|
|
|
document.getElementById("playctl").style.display = "none";
|
2012-06-07 15:43:06 -07:00
|
|
|
document.getElementById("startgame").style.display = "block";
|
2012-05-22 20:54:33 -07:00
|
|
|
document.getElementById("login").style.display = "none";
|
|
|
|
|
document.getElementById("register").style.display = "none";
|
2012-06-18 14:30:05 -07:00
|
|
|
document.getElementById("current").style.display = "block";
|
|
|
|
|
getcurrent();
|
2012-05-22 20:54:33 -07:00
|
|
|
}
|
|
|
|
|
else if (mode == "login") {
|
|
|
|
|
document.getElementById("keyboard").style.display = "none";
|
2012-07-10 13:53:38 -07:00
|
|
|
document.getElementById("playctl").style.display = "none";
|
2012-06-07 15:43:06 -07:00
|
|
|
document.getElementById("startgame").style.display = "none";
|
2012-05-22 20:54:33 -07:00
|
|
|
document.getElementById("login").style.display = "block";
|
|
|
|
|
document.getElementById("register").style.display = "none";
|
2012-06-18 14:30:05 -07:00
|
|
|
document.getElementById("current").style.display = "block";
|
|
|
|
|
getcurrent();
|
2012-05-22 20:54:33 -07:00
|
|
|
}
|
|
|
|
|
else if (mode == "register") {
|
|
|
|
|
document.getElementById("keyboard").style.display = "none";
|
2012-07-10 13:53:38 -07:00
|
|
|
document.getElementById("playctl").style.display = "none";
|
2012-06-07 15:43:06 -07:00
|
|
|
document.getElementById("startgame").style.display = "none";
|
2012-05-22 20:54:33 -07:00
|
|
|
document.getElementById("login").style.display = "none";
|
|
|
|
|
document.getElementById("register").style.display = "block";
|
2012-06-18 14:30:05 -07:00
|
|
|
document.getElementById("current").style.display = "none";
|
2012-05-22 20:54:33 -07:00
|
|
|
}
|
2012-07-14 09:46:26 -07:00
|
|
|
wsCurrent();
|
2012-05-22 20:54:33 -07:00
|
|
|
}
|
|
|
|
|
|
2012-06-23 17:11:51 -07:00
|
|
|
function toggleBlock(id) {
|
|
|
|
|
var element = document.getElementById(id);
|
|
|
|
|
if (!element)
|
|
|
|
|
return;
|
|
|
|
|
if (element.style.display != "block")
|
|
|
|
|
element.style.display = "block";
|
2012-06-20 14:11:57 -07:00
|
|
|
else
|
2012-06-23 17:11:51 -07:00
|
|
|
element.style.display = "none";
|
2012-06-20 14:11:57 -07:00
|
|
|
}
|
|
|
|
|
|
2012-07-11 11:10:50 -07:00
|
|
|
function message(msg, mtype) {
|
2012-07-10 08:08:54 -07:00
|
|
|
var msgdiv = document.createElement("div");
|
|
|
|
|
var msgtext = document.createTextNode(msg);
|
|
|
|
|
msgdiv.appendChild(msgtext);
|
2012-07-11 11:10:50 -07:00
|
|
|
if (mtype) {
|
|
|
|
|
msgdiv.className = mtype;
|
|
|
|
|
}
|
2012-07-10 08:08:54 -07:00
|
|
|
var msgcontainer = document.getElementById("messages");
|
|
|
|
|
msgcontainer.insertBefore(msgdiv, msgcontainer.firstChild);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
function debug(level, msg) {
|
|
|
|
|
if (level < debugSuppress)
|
|
|
|
|
return;
|
|
|
|
|
var msgdiv = document.createElement("div");
|
|
|
|
|
var msgtext = document.createTextNode(msg);
|
|
|
|
|
msgdiv.appendChild(msgtext);
|
|
|
|
|
document.getElementById("debug").appendChild(msgdiv);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-10 18:39:36 -07:00
|
|
|
function setTitle(tstr) {
|
|
|
|
|
message(tstr);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
function textsize(larger) {
|
|
|
|
|
var cssSize = termemu.view.style.fontSize;
|
|
|
|
|
if (!cssSize) {
|
2012-06-23 19:13:34 -07:00
|
|
|
return null;
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
var match = cssSize.match(/\d*/);
|
|
|
|
|
if (!match) {
|
2012-06-23 19:13:34 -07:00
|
|
|
return null;
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
var csize = Number(match[0]);
|
|
|
|
|
var nsize;
|
|
|
|
|
if (larger) {
|
|
|
|
|
if (csize >= 48)
|
|
|
|
|
nsize = 48;
|
|
|
|
|
else if (csize >= 20)
|
|
|
|
|
nsize = csize + 4;
|
|
|
|
|
else if (csize >= 12)
|
|
|
|
|
nsize = csize + 2;
|
|
|
|
|
else if (csize >= 8)
|
|
|
|
|
nsize = csize + 1;
|
|
|
|
|
else
|
|
|
|
|
nsize = 8;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (csize <= 8)
|
|
|
|
|
nsize = 8;
|
|
|
|
|
else if (csize <= 12)
|
|
|
|
|
nsize = csize - 1;
|
|
|
|
|
else if (csize <= 20)
|
|
|
|
|
nsize = csize - 2;
|
|
|
|
|
else if (csize <= 48)
|
|
|
|
|
nsize = csize - 4;
|
|
|
|
|
else
|
|
|
|
|
nsize = 48;
|
|
|
|
|
}
|
2012-06-23 17:41:27 -07:00
|
|
|
var cssvalstr = nsize.toString() + "px";
|
|
|
|
|
document.getElementById("term").style.fontSize = cssvalstr;
|
|
|
|
|
document.getElementById("keys").style.fontSize = cssvalstr;
|
2012-05-09 13:38:05 -07:00
|
|
|
termemu.fixsize();
|
2012-05-06 08:45:40 -07:00
|
|
|
debug(1, "Changing font size to " + nsize.toString());
|
2012-06-23 19:13:34 -07:00
|
|
|
return nsize;
|
2012-05-06 08:45:40 -07:00
|
|
|
}
|
|
|
|
|
|
2012-06-20 11:37:05 -07:00
|
|
|
function idlestr(ms) {
|
|
|
|
|
if (typeof(ms) != "number")
|
|
|
|
|
return "?";
|
|
|
|
|
var seconds = Math.round(ms / 1000);
|
|
|
|
|
var ss = String(seconds % 60);
|
|
|
|
|
if (ss.length < 2)
|
|
|
|
|
ss = "0" + ss;
|
|
|
|
|
var mm = String(Math.floor((seconds % 3600) / 60));
|
|
|
|
|
if (mm.length < 2)
|
|
|
|
|
mm = "0" + mm;
|
|
|
|
|
var hh = String(Math.floor(seconds / 3600));
|
|
|
|
|
if (hh.length < 2)
|
|
|
|
|
hh = "0" + hh;
|
|
|
|
|
return hh + ":" + mm + ":" + ss;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-06 08:45:40 -07:00
|
|
|
function bell(on) {
|
|
|
|
|
var imgnode = document.getElementById("bell");
|
|
|
|
|
if (on) {
|
|
|
|
|
imgnode.style.visibility = "visible";
|
|
|
|
|
window.setTimeout(bell, 1500, false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
imgnode.style.visibility = "hidden";
|
|
|
|
|
return;
|
|
|
|
|
}
|