Saturday, December 11, 2010

Persistent, Aren't You?

One of the big questions for almost every project is how to persist the data.  Common forms include:

  • Flat files (XML, JSON, etc)
  • Databases (SQL, NoSQL, etc)
  • RAM
Now, granted, that last one isn't used very often.  You'd have to have a system that never goes down, or a series of redundant systems that always keep at least 1 system up at all times.  That's pretty tough to guarantee.  Of course, if you don't care that your data disappears during an outage (like with a caching server) then RAM is perfect.

Flat files are useful mainly when you just can't have a database, for some reason.  They're also useful when dealing with documents.

SQL databases (aka Relational Databases) are useful for data that has many parts that are related to each other.

NoSQL databases are useful for document storage, with minimal relationships.  They also tend to be easily horizontally scalable.

When I started working on the MUD, I was pretty sure I was going to use CouchDB or another NoSQL database for a few reasons:

  • Horizontal scaling
  • MUD accounts could be easily stored as documents.
When creating a SQL database for a MUD, you have a lot of tables to deal with, including Users, Characters, Items, Rooms, NPCs, and more.  Creating the relationships between them involves quite few many-to-one and many-to-many relationships.

On the other hand, a NoSQL database could store the user's account and everything attached to it as 1 big record.  Each area in the world could be another, etc.  It would simplify the data access quite a bit.

But in the end, I decided I didn't want to limit it to any of these.  I'll be writing a system that will store the data in any of the above methods simply by setting that information in the configuration files.  It should even be possible to create conversion tools that quickly convert from 1 format to another.  This would make backups or migrations quite easy.

And there's one more thing it makes easy:  Testing.  I will be creating a mock data store that can be used to feed any data into the system at will.  That'll make unit tests quite a bit easier and faster.

Wednesday, December 8, 2010

Decisions, Decisions

So there it was:  The first decision.

And for a programming project, that decision is often what language to use.  Quite often, the language is dictated by the project itself.  But other times, just about any language would do.

For this project, a text-based game library and MUD built on it, I had quite a few options.  I had previously worked on TigerMUD in C#.  I could fall back to that project, or start an entirely new codebase.  My day job requires a lot of PHP and Javascript.  PHP isn't ideally suited for the job, but could do it.  Javascript has recently become more as an actual programming language, and not just a scripting language.

But instead I chose Ruby.  My initial reasons were:

  • I wanted to learn it.
  • I had previous used it to make a MUD proxy to allow regular telnet access to a proprietary MUD.
  • It has a lot of libraries, almost all of which are very open on their licensing.
  • It has the built-in ability to reload code from disk while running without any hassle.
Those reasons were about equal, actually.  At least, at the time.  The last one is the most interesting, but also the least useful after all.

In TigerMUD, we spent a lot of time and effort making the MUD able to load the code from disk, recompile it and replace the currently-running code without kicking off any users.  There were many roadblocks, including a memory leak that forced us to partition our code more strictly than we wanted.  See, any code that was loaded was added to memory.  It didn't replace the existing memory locations used.  And to free that memory again, you had to completely dump everything in that partition.  We did it, and it worked very well when we were done, but it was quite the hassle.

With Ruby, you simply tell it to include the code again and you're done.  No muss, no fuss.  However, there's a caveat:  Enabling that means leaving your code open to some attacks.  Your code has to run at a lower safety level, and that's inherently dangerous.  It's probably possible to make your code secure enough that it is acceptable, but it seems too risky to me.  At least for now.

Instead, I plan to solve that problem a different way:  The system will be able to transfer MUD data between servers without interruptions.  To reload the code on a server, you move all the players, NPCs and rooms off the server and onto another one.  Then you bring that server down and back up, with the new code.  Then it can take some data and the next server can do its upgrade routine.

Before I get to that point, I may find another way yet to handle it.  And if I do, I'll weigh the options at that time.

Tuesday, December 7, 2010

A New Beginning

Some time ago, I decided to write a game. It wasn't really a conscious decision, but it has colored everything I've done for many years now. I finally feel ready to start, and most of my prep work has gone towards making a MUD. So I guess that's what I unconsciously decided to build.

I've got a few years of ideas in my head about how my ideal MUD would work, including gameplay and backend mechanics.

I have already started working on this MUD. I've got some basic things done and I'm moving on to more complicated things. I will probably discuss my existing decisions, also.

This blog will be used to describe my experiences coding the MUD, and the decisions I make along the way.

I have some basic must-haves for the MUD. A partial list, in no particular order:
  • Skill-based advancement
  • Combat system(s)
  • Magic system(s)
  • Crafting system(s)
  • Scalable server architecture
  • Access API (to allow many different kinds of clients: Telnet, web, etc.)
Quite a few other things will be decided as they come up, such as how to build rooms and items and NPCs (in-game vs another client), etc.

I don't intend to use this blog to defend my ideas and decisions. I may incorporate any ideas mentioned by commenters, but I may also completely ignore the ideas. No offense intended, but this is my game.

I will be open sourcing the code for the server itself. Other game-specific code, and the art assets, will remain my property. This will allow others to create their own worlds, but also allow me to keep my world somewhat unique.  After I get to a certain point, I'll be looking at accepting code contributions, but I'll be very strict on contributions, even with style considerations.  I'll definitely be requiring that all unit tests pass, and new code is properly tested with new tests.

My intention is to make the open sourced code able to be used for different purposes as well. A MUD is one possibility, of course, but I would like to see it able to make Interactive Fiction and other standalone games, as well as other multiplayer games as well.