From 1b8917f2c7e6967a7859ec79280a4b79ead74651 Mon Sep 17 00:00:00 2001 From: deuce <> Date: Fri, 27 Sep 2019 00:52:25 +0000 Subject: [PATCH] Implement mail. Only Hail is left on the TODO pile. --- xtrn/lord2/lord2.js | 272 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 242 insertions(+), 30 deletions(-) diff --git a/xtrn/lord2/lord2.js b/xtrn/lord2/lord2.js index c95a425005..711a2ca775 100644 --- a/xtrn/lord2/lord2.js +++ b/xtrn/lord2/lord2.js @@ -586,7 +586,7 @@ var vars = { '`g':{type:'int', val:3}, // TODO: >= 3 is ANSI or something... '`x':{type:'const', val:' '}, '`d':{type:'const', val:'\b'}, - '`\\':{type:'const', val:'\r\n'}, + '`\\':{type:'const', val:'\r'}, '`*':{type:'const', val:dk.connection.node}, x:{type:'fn', get:function() { return player.x }, set:function(x) { player.x = clamp_integer(x, 's8') } }, y:{type:'fn', get:function() { return player.y }, set:function(y) { player.y = clamp_integer(y, 's8') } }, @@ -1302,8 +1302,10 @@ function update_bar(str, msg, timeout) } l = 76 - dl; str = str + spaces(l); - if (timeout !== undefined) + if (timeout !== undefined) { + // TODO: Apparently, the time is supposed to be relative to the message len... bar_timeout = new Date().valueOf() + parseInt(timeout * 1000, 10); + } else bar_timeout = undefined; current_saybar = str; @@ -1415,6 +1417,37 @@ function ranked_players(prop) return ret.sort(sortfunc); } +function chooseplayer() +{ + var i; + var pl; + var pn; + var ch; + + lln('`r0`2 Who would you like to send a message to?'); + sln(''); + lln(' `2(`0full or `%PARTIAL`0 name`2).') + lw(' `2NAME `8: `%'); + pn = superclean(dk.console.getstr({len:26})); + sln(''); + + for (i = 0; i < pfile.length; i++) { + pl = pfile.get(i); + if (pl.name.indexOf(pn) !== 0) { + lw('\r'); + dk.console.cleareol(); + lw(' `2You mean `0'+pl.name+'`2? [`0Y`2] `8: '); + ch = getkey().toUpperCase(); + if (ch !== 'N') + ch = 'Y'; + if (ch === 'Y') + return i; + } + } + lw('`\\ `2Sorry - no one by that name lives \'round these parts.`\\'); + return undefined; +} + function run_ref(sec, fname) { var line; @@ -2675,34 +2708,12 @@ rescan: throw('Unknown clear type at '+fname+':'+line); }, 'chooseplayer':function(args) { - var i; - var pl; - var pn; - var ch; + var pl = chooseplayer(); - lln('`r0`2 Who would you like to send a message to?'); - sln(''); - lln(' `2(`0full or `%PARTIAL`0 name`2).') - lw('`2NAME `8: `%'); - pn = superclean(dk.console.getstr({len:26})); - sln(''); - - for (i = 0; i < pfile.length; i++) { - pl = pfile.get(i); - if (pl.name.indexOf(pn) !== 0) { - lw(' `2You mean `0.`2? [`0Y`2] `8: '); - ch = getkey().toUpperCase(); - if (ch !== 'N') - ch = 'Y'; - if (ch === 'Y') { - setvar(args[0], i + 1); - return; - } - lw('\r'); - dk.console.cleareol(); - } - } - lw('`\\; `2Sorry - no one by that name lives \'round these parts.`\\'); + if (pl === undefined) + setvar(args[0], 0); + else + setvar(args[0], pl + 1); }, 'drawpart':function(args) { var x = getvar(args[0]); @@ -2813,6 +2824,9 @@ rescan: lw(' `2'+space_pad(pl.name, 29)+'`%'+space_pad(pl.p[8].toString(), 14)+'`0'+mp.name); } }); + }, + 'checkmail':function(args) { + mail_check(false); } }; @@ -3051,6 +3065,91 @@ function update_space(x, y) }); } +function mail_check(messenger) +{ + var fn = getfname(maildir+'mail'+(player.Record + 1)+'.dat'); + var f = new File(getfname(maildir+'mat'+(player.Record + 1)+'.dat')); + var l; + var m; + var op; + var ch; + var reply = []; + + if (!file_exists(fn)) + return; + + if (messenger) { + update_bar('`2A messenger stops you with the following news. (press `0R`2 to read it)', true); + do { + ch = getkey().toUpperCase(); + } while (ch !== 'R'); + lw('`r0`c'); + } + + // TODO: Not sure what happens on windows of someone else has the file open... + // We likely need a file mutex here. + file_rename(fn, f.name); + if (!f.open('r')) + throw('Unable to open '+f.name); + while(1) { + l = f.readln(); + if (l === null) + break; + m = l.match(/^@([A-Z]+)(?: (.*))?$/); + if (m !== null) { + switch (m[1]) { + case 'KEY': + more(); + break; + case 'MESSAGE': + lln(' `2"Message from `0'+m[2]+'`2,".'); + sln(''); + lln('`0 '+repeat_chars(ascii(0xc4), 77)); + reply = []; + break; + case 'REPLY': + op = parseInt(m[2], 10); + if (isNaN(op)) + throw('Invalid REPLY ID'); + op = pfile.get(op - 1); + if (op === null) + throw('Invalid record number '+op+' in REPLY'); + lw(' `2Reply to `0'+op.name+'`2? [`0Y`2] : `%'); + do { + ch = getkey().toUpperCase(); + if (ch === '\r') + ch = 'Y'; + } while('YN'.indexOf(ch) === -1); + if (ch === 'Y') { + if (op.deleted) { + lln('`\\ `2You decide answering someone who is dead would be useless.`\\'); + } + else { + mail_to(op.Record, reply); + } + } + break; + case 'DONE': + lln('`0 '+repeat_chars(ascii(0xc4), 77)); + sln(''); + break; + } + } + else { + if (l.substr(0, 4) === ' `2') + reply.push(' `0>`3'+l.substr(4)); + if (l !== '') + lln(l); + } + } + if (messenger) { + sln(''); + more(); + draw_map(); + update(); + } +} + var next_update = -1; function update(skip) { var i; @@ -3113,6 +3212,7 @@ function update(skip) { other_players = nop; timeout_bar(); + mail_check(true); } dk.console.gotoxy(player.x - 1, player.y - 1); foreground(15); @@ -3844,6 +3944,110 @@ function offline_battle() redraw_bar(true); } +function mail_to(pl, quotes) +{ + var wrap = ''; + var l; + var ch; + var bt = 0; + var msg = []; + var f; + var op = pfile.get(pl); + + if (op === null || op.deleted) + throw('mail_to() illegal user'); + + lln(space_pad('`\\`r1 `%COMPOSING YOUR MASTERPIECE', 78)+'`r0'); + sln(''); + if (quotes !== undefined) { + quotes.forEach(function(l) { + lln(l); + msg.push(l); + }); + sln(''); + } + + do { + l = wrap; + wrap = ''; + foreground(10); + sw(' >'); + foreground(2); + sw(l); + do { + ch = getkey(); + if (bt === 1) { + bt = 0; + if ('0123456789!@#$%'.indexOf(ch) > -1) { + l += ch; + lw('\r`0 >`2'+l+' \b'); + continue; + } + else { + lw('\b \b'); + l = l.slice(0, -1); + continue; + } + } + else { + if (ch === '`') + bt = 1; + } + if (ch === '\x08') { + if (l.length > 0) { + l = l.slice(0, -1); + if (l.substr(l.length-1) === '`') { + bt = 1; + lw('\r`0 >`2'+l); + sw('` \b'); + } + else { + sw(ch); + sw(' \x08'); + } + } + } + else if (ch !== '\x1b') { + sw(ch); + if (ch !== '\r') { + l += ch; + } + if (displen(clean_str(l)) > 77) { + t = l.lastIndexOf(' '); + if (t !== -1) { + wrap = l.slice(t+1); + l = l.slice(0, t); + sw(bs.substr(0, wrap.length)); + sw(ws.substr(0, wrap.length)); + } + ch = '\r'; + } + } + } while (ch !== '\r'); + if (l.length === 0 && msg.length === 0) { + sln(''); + lln(' `2Mail aborted'); + return; + } + l = clean_str(' `2' + l); + if (l.length >= 5) + msg.push(l); + sln(''); + } while (l.length >= 5); + msg.unshift('@MESSAGE '+player.name); + msg.push('@DONE'); + msg.push('@REPLY '+(player.Record + 1)); + f = new File(getfname(maildir + 'mail' + (pl + 1) + '.dat')); + if (!f.open('ab')) + throw('Unable to open file '+f.name); + msg.forEach(function(l) { + f.write(l+'\r\n'); + }); + f.close(); + sln(''); + lln(' `2Mail sent to `0'+op.name+'`2'); +} + function do_map() { var ch; @@ -4009,7 +4213,15 @@ function do_map() run_ref('closestats', 'gametxt.ref'); break; case 'W': - // TODO: Write mail (multiplayer) + sclrscr(); + ch = chooseplayer(); + if (ch !== undefined) { + sln(''); + sln(''); + mail_to(ch); + } + draw_map(); + update(); break; case 'Y': run_ref('yell', 'help.ref'); -- GitLab