Saturday, 9 March 2013

Interesting problem with TermInfo

So I'm writing my formatter to actually make use of the provided TermInfo characteristics of the connection, instead of just assuming that it was ANSI compliant. And all has gone fairly well. The code is unit tested, and I know it works. So I plugged it in, and connected to the server using telnet. And the initial menu was missing formatting that it had before.

What gives?

I tried changing terminal types a couple of times, in case the terminfo data was wrong. I tried a few other things. I then randomly hit enter on the menu, which causes the menu to re-render. And this time, the rendered menu had the formatting.

So I fired up Wireshark and watched. It turns out, the menu is initially sent before the Terminal Type option response is received, so when it is first rendered we have no details about the terminal type, and so assume that formatting isn't possible. It's technically wrong, but it's safe. And I'm happier with safe than I would be with spewing garbage on the screens.

Sunday, 3 March 2013

Data Stores

As always with me, the choice of data store is actually quite a difficult one. There are so many different choices these days, with different pros and cons between them. Ultimately in this case it came down to two different requirements:

  • Document Store or Relational Table Store
  • Transactional or Non-Transactional
The second one is actually tied to the first in this case. Transactional only matters if you are going to be updating multiple target records at a time. In a Relational Table Store this is almost certainly going to be the case, but in a Document Store you can architect it so that the single document you are storing contains everything so you don't need to do multiple-record updates.

The third, secret requirement actually narrowed the field even more. This is the fact that I must be able to use the store during unit testing - if it's not tested it doesn't work! - which removed a lot of the NoSQL field from play. For Relational Table Stores - i.e. SQL databases - I can use HSQL or Derby during unit testing for a representation of the final database, and likely PostgreSQL as the real production store. For a Document Store, MongoDB has a library somebody wrote to allow you to run an embedded version, which is perfect for unit testing. The library actually downloads, unpacks and runs MongoDB of the appropriate version for you to use, and tidies up afterwards.

I've actually chosen to go with MongoDB for this, in part because I've not yet successfully written a project with it (and I'm a glutton for punishment) and in part because I think the Document Store is actually going to be a good fit. It means, for example, I can store entire character details - their equipment, skills, stats, etc - as a single Document and not as details spread across many different tables. We shall see how it goes.

Output Formatting

One of the things I've done so far is to write a formatter library that will - eventually - be driven by TermInfo and Charset data retrieved from the connection. (Currently it's hard-coded, which is bad but easy). The idea here is that everything in the MUD itself can then output messages in the internal markup language, which happens to be XML based (There is a reason) and the formatter then converts this to the appropriate byte stream to achieve as close as wanted on the client.

What does this look like? Well, the following:

The idea here is that if the terminal at the other end supports ANSI colours, then ANSI colour escape sequences will be emitted as appropriate to change the colours. If the terminal doesn't support colour at all then no colours will be emitted but the text still will. This way you don't get garbage on the screen because of your terminal settings, and you don't need to configure your terminal to work the way the server expects.

I've only done colours, newlines and underlines so far, but it works pretty well. More will be added as necessary.