A Better Design

[ LiB ]

The design of the SimpleMUD was basic, because it assumed you were going to use Telnet to access the MUD. Telnet is a great protocol in the fact that almost every operating system in the world has built-in clients . This means that you can log into any Telnet MUD anywhere using any client, which is one of the main claims to fame of MUDs. They're lightweight clients; you don't need to have certain system specs to play a game; as long as you have a Telnet client. Years ago, I had a simple PDA (Sharp Zaurus, I think) with a built-in modem and a Telnet client. On this little hand-held thing, I could log in to any MUD in my area. You wouldn't believe how cool that was.

Competition from the Big Boys

Unfortunately, ever since the release of Ultima Online , the bar has been raised on persistent world games . No, that's not quite correct; Ultima Online literally grabbed the bar and yanked it as far high as they could. I was playing on a few different MUDs in 1997, and then suddenly, every one disappeared!

Where did they all go? To graphical MUDs, also known as MMORPG s. For the past few years, I've seen MUDs practically go the way of the dinosaurs, and that's for a very simple reason; Telnet clients just don't cut it. Sometimes it's much more entertaining to have the client of a full-blown game handed to you, which takes care of everything, and removes the need to type so much.

Sometimes I find myself thinking that Telnet is too limiting. Only 15 colors, very limited text controls, and so on. Modern clients should be able to support more than 15 colors, for crying out loud!

Designing a Flexible System

Unfortunately, I don't have the room or the time to go over creating a new client for use with the BetterMUD (Hey, server development is more fun anyway!), but that's no excuse for assuming we'll be using Telnet!

The key to a good MUD is extensibility and the ability to adapt to future capabilities. Unfortunately, no one can predict every feature that may be needed in the future (I bet people would pay good money for that ability though), so you need to make sure your design is inherently flexible by abstracting out certain things.

In Chapter 11 you learned the concept of abstracting physics and logic. This same concept can be applied to the networking system. Instead of abstracting the physics and logic, I'm going to abstract the physics and the protocol away from each other.

For example, when a player enters a room in the BetterMUD, everyone in that room must be told about the new entry. This can be done in many ways; you could assume the client is text based, and just shoot off a string. Instead of doing that, though, you may want to think about what a future protocol might be like.

NOTE

The MUDs Return

One gleam of hope is emergingMUDs are making a comeback, and this is happening for many reasons.

First of all, ever since the MMORPG explosion, there have been dozens of clones , but very few of them actually manage to be good and entertaining. Many are disasters (and a few didn't even work right out of the box... oy!). Even worse are the monthly charges. Back in the mid- to late-80s, most MUDs were run on a per- hour basis, but that was because they used so much power. As computers became faster and cheaper, running a MUD became cheaper, and more people could afford to run them.

By the mid-90s, almost all the MUDs I knew were completely free of charge, and now I can't find a MUD that charges fees! Times are great indeed; I can't believe I'm running not one, but two MUDs of my own now. When I first started playing them, I would have never dreamed this was possible.

Another reason why MUDs are making a comeback is because MMORPGs are too big . When they first came out, they were novel , and you could play with tens of thousands of people at a time. But in reality, that's a heck of a lot of people in a game. People tend to like the small-knit communities that MUDs offer naturally, instead of the megalopolis approach of MMORPGs. It's easier to get to know people, and you enjoy yourself more.

Consider a graphical client that knows about character graphics and keeps track of all the characters in the game. Instead of notifying that kind of client in text form, you can probably shoot off a packet containing the information "character X entered from portal Y", and then let the client figure out how to display that information, for example by showing a graphical animation of the character coming through a door.

So the main concern here is translating physical MUD events into data that is reported back to a client.

Reporters

For reporting events to a client, I have created the idea of a reporter . Figure 16.1 shows the relationship between the game, characters, and reporters (new components are shaded gray) combined with the connection, protocol, and handler objects you should already be familiar with.

Figure 16.1. The reporter system combined with familiar elements of the connection protocol and handler objects.

graphic/16fig01.gif


If you recall from Part Two of the book, the SimpleMUD implemented most game logic inside of a Telnet handler named Game . In the BetterMUD, the game module is actually completely abstracted from anything dealing with Telnet; it doesn't care what protocol people use.

The game informs characters about actions that happen in the game, such as players entering or leaving the realm, items being dropped, and so on. When the character receives an action, he needs to decide what to do with that action. If the character is a player, the character has a reporter object, and the character passes the command along to the re-porter. Figure 16.1 shows a split at this pointan action can go either to a Telnet reporter or a graphic reporter. In the game, every player character has one reporter object; which means that if the character's connected to the game with Telnet, he sends the action to a Telnet reporter.

Once it receives the action event, the reporter figures out how to tell the client what happened . A simple Telnet reporter makes a string out of the action and sends that off. More complex protocols probably require the creation of a complex packet object and its shipping.

That's the design for the reporting system. It allows you to add more protocols in the future, so you can support more complex clients.

Reporter Design

Reporters are basically just special logic modules that are given to players in the game. Every time a player's logic collection is told about a game action, the reporter logic module for that player is told as well. Because of this, they inherit from the Logic class, as shown in Figure 16.2, which shows a simple design, with two possible implementations .

Figure 16.2. Reporter classes inherit from the Logic class.

graphic/16fig02.gif


Telnet Reporters

I only had time to actually implement one reporter class for the BetterMUD, a version that uses Telnet to communicate with players. It's quite simple, but you should feel free to make better versions of your own.

Here's the class definition with most of the helper functions stripped out:

 class TelnetReporter : public Logic { public:     TelnetReporter(         entityid p_id,                              // ID of character         Connection<BetterTelnet>* p_conn )          // address of connection         : m_id( p_id ),           m_conn( p_conn )    {}     std::string Name() { return "telnetreporter"; }     bool CanSave() { return false; }     int DoAction( const Action& p_action );     void SendString( const std::string& p_string ); protected:     SocketLib::Connection<BetterTelnet>* m_conn;     entityid m_id; };  // end class TelnetReporter 

The class only needs to respond to the DoAction events that it receives, and send messages to its connection ( m_conn ) when it needs to. As I mentioned earlier, some logic modules shouldn't be saved to disk, and reporter modules are a perfect example of that. They are only valid when players are connected, so there's no reason to write them to disk.

Here's a sample from the DoAction function:

 int TelnetReporter::DoAction( const Action& p_action ) {     if( p_action.actiontype == "enterroom" )         EnterRoom( p_action.data1, p_action.data2 );     else if( p_action.actiontype == "leaveroom" )         LeaveRoom( p_action.data1, p_action.data2 );     else if( p_action.actiontype == "say" ) {         character c( p_action.data1 );         SendString(             "<$yellow>" + c.Name() +             " says: <$reset>" + p_action.stringdata );     } 

This code snippet takes care of three actions: players entering a room, leaving a room, or speaking. The first two actions simply call the LeaveRoom and EnterRoom helpers (which are helpers that print out information about characters leaving and entering the room), and the third action is simple enough that you can just call the SendString helper function to directly send some text to the connection.

The strings <$yellow> and <$reset> are special additions to my better Telnet protocol, which I go over in the next section.

State Changes

BetterMUD uses a fairly simple state system. This section deals with how the reporter class handles changing between states. The existence of the reporter on a player means that the player's connection is in the "game" state (much like the SimpleMUD). I've also got something new, a "menu" state, in which players can manage their characters.

There are two special actions that deal with changing physical connection states inside the reporter. They deal with the connection being hung up, and the connection leaving the game state. Here they are (these are within the DoAction function I showed you earlier):

 else if( p_action.actiontype == "hangup" ) {     m_conn->Close();     m_conn->ClearHandlers(); } else if( p_action.actiontype == "leave" ) {     m_conn->RemoveHandler(); } 

When a connection is told to hang up, the reporter simply closes the connection and tells the connection to remove all its handlers. This act makes the connection leave the handler it is currently in, so you don't need to perform any other cleanup code, just as long as the game handler logs off correctly (which it does).

On the other hand, the Leave function is called when the player quits the game. Figure 16.3 shows the process of entering and leaving the game, starting from the menu state. When a player enters the game, the menu handler remains on the stack and it isn't removed until the player quits from the menu.

Figure 16.3. The connection handler stack looks like this throughout the game.

graphic/16fig03.gif


When a player enters the game, the function swaps out the enter game handler with the game handler, and it never removes the menu handler. Therefore, when the player quits the game, the connection handler takes him back to the menu state.

[ LiB ]


MUD Game Programming
MUD Game Programming (Premier Press Game Development)
ISBN: 1592000908
EAN: 2147483647
Year: 2003
Pages: 147
Authors: Ron Penton

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net