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.

Thursday, 21 February 2013

Client Capabilities

What I've done so far is written a fully featured Telnet server, which includes support for Telnet option negotiation, covering the Options for Negotiate About Window Size, Charset, Terminal Speed and Terminal Type, and I've written a Terminfo module that is plugged into the Terminal Type handler so I can use Terminfo details to determine how to send bytes back to the client. The theory there being that any arbitrary client will work and as long as my terminfo settings know about it then things will be grand, with no configuration needed from the client side.
I've then been playing with various MUD clients - pretty much all of the ones that are available on Ubuntu by default, plus a couple of Windows ones using Wine - and have been appalled at their level of support. The only client I've tried that supported the CHARSET option and claimed to support Unicode was MUSHClient - and that includes the standard telnet program. And the only MUD client that actually supported any Terminal Types that are present in the standard Terminfo database was gnome-mud - which falls back to xterm.
I'm less convinced that was a useful way to spend my time, but it was an interesting experience writing code to process the terminfo database :)

What am I doing?

I've always been interested in MUDs - ever since I first came across the genre about 15-20 years ago. The fact that there aren't any real graphics and everything is story driven really appeals to me.
So, I'm writing myself a MUD engine. Mostly as a learning experience, since it covers a lot of areas of game development without any of the complicated bits of needing to do graphics and audio. I'm doing it in Java as a totally, 100% from scratch codebase - because Java actually brings a lot to the table that is very useful for this kind of development, even though it's generally not as good for game development for various reasons. In specific the networking has been a doddle - see a future post - and I can imagine adding scripting in will be equally easy with the benefits of JSR-223. 
I know full well that it's likely to not go anywhere, but it's an interesting project and actually covers quite a lot of ground that is best learnt by actually doing it instead of reading Internet posts. Plus there's not a huge amount of stuff on the Internet covering this type of thing. And if I actually do manage to get it up and running, then that's great :)