Wednesday, 29 January 2014

Roguelike MUD progress #7 - Web-based client

Previous post: Roguelike MUD progress #6

I set a mini-goal for myself, to display a curses-based program on a web page.

The first step was to find a no frills, easy to adopt and extend Python websocket solution. One I've stumbled on  few times, is the simple websockets client/server gist. I used a slightly fixed version of it as a base. The next step was to find decent web-based terminal emulation. There are frameworks available which ditch the terminal window, but they come with larger problems.  The best candidate is term.js.

So taking the simple websockets simple_websocket_client.html and adding term.js, then modifying, it was easy to get a simple echo working with embedded ANSI control sequences.

First, I tried to proxy the input and output from the nano editor. Unfortunately, doing this with the subprocess module resulted in nano outputting a message about not supporting redirection.  There's probably a way to do this, but too much bother and it is not really my goal anyway.

Next, I went for something simpler.  I did a simple proxying of input and output to a telnet connection. Specifically my Roguelike MUD codebase.  There were some teething problems.  Text incoming from the browser-based terminal through the websocket, is UTF-8 encoded.  And similarly, outgoing text has to be as well.  But responses from the MUD contain both ANSI escape sequences and telnet negotiation sequences.  In order to work around this, I stripped the telnet negotiation out of outgoing text, and modified the relatively basic websocket code to also send binary frames.

A working connection:

In-game display:

As the picture above shows, the ANSI sequences are working perfectly.  But the character set does not seem to contain the line drawing characters.  My game interface already has debugging tools which display accessible character sets.

The main character sets:

As can be seen above, the only character set with even a hint of line drawing characters, is the one exposed through the ESC(0 ANSI sequence.  Most of these sequences are faked by term.js, where known character sets are mocked up from the underlying unicode-supporting font.

One solution is to do what I do with Putty, which is to identify the connected client, and if it's one which supports unicode, then switch unicode on using terminal control sequences.  Modifying term.js to respond to the ENQ character (0x05), and send it's terminal name (xterm) was easy enough.

This is what I should be seeing now:

This is what I am actually seeing:

The correct unicode characters are being sent, but not being displayed correctly by term.js.  I don't expect this will be that difficult to correct when I get some more time to work on this.