SourceForge.net Logo
LinuxLinks

Docs

Ok, this may look as a bad joke ;-). Though, I'll try to place here some usefull informations.

Basic concepts

Rooms, livings and items

Our environment consits of three basic objects. Every object has its description and some other properties accessible throug the mudObject class' methods.
Rooms contains everything what can be seen on the MUD. They are connected with exits, so user can go through them. Most of exits are visible in room's description, but there may be hidden exits or even special exits, which aren't shown at all or uses special command for passing them. Every room should have title (i.e. very short description). There can be two types of objects in rooms: characters (livings - NPCs or entites - players) and items. Rooms are represented by mudRoom class.
Items are objects user can manipulate with - doors (open/close, lock/unlock), food and drink (eat, drink), weapons and armours (wear/remove, wield/unwiled) etc. Items can by owned by room or by other items.
Characters are objects controlled by computer (NPCs) or by user. They're always in some room (accessible via mudObject::getParentRoom() and can possess items. Users can interact with them using ask command (ask <who> [to|for|about] <something>)
If everything goes well, complete room description can look like this one:
Small square
Nice fountain is located in the center. Ground is paved with grey paving stones. You see a shop in the northeastern corner and very magnificent house on the west. Through the narrow street on the north you can be seen trees. To the south direction leads wide street and other one leads to the east.
Exits: [east, house[#], north, shop]
Items: [bread, milk]
citizen is standing here.

Extending existing objects

However it is possible to extend objects (i.e. room, items, characters) using standard C++ mechanism, it isn't very pretty (save/load problems). Because of this reason, we're using events and actions. Events reacts on some thing that happend. They are collected in actions.
When new behaviour is needed, programmer inherits some event class, add it to some action and assigns that action to some object. This information is stored as string-string map, so it is very easy to save such data. Actions are managed by action manager.
Events can be divided by many aspects, so there are listed by class:

Some examples

Let's say that we want npc, which will greet player, which enters the room, and says something some period of tie. This can be done by implementing two events - mudLivingEvent for greeting and mudGlobalEvent for saying. But the object for second event must contain information about relevant living. This can be inefficient and undesirable. Luckily, mudServer provides mechanism for translating global events to local events (mudLivingEvent).
#include <mud_events.h>
#include <mud_server.h>

// just implement new class based on mudLivingEvent
class greetEvent : public mudLivingEvent {
  public:
    // standard constructor and destructor
    greetEvent() : mudLivingEvent() {};
    virtual ~greetEvent() {};

    // this method is called when the event is invoked
    virtual void invoke(mudLiving *receiver, mudLiving *from, mudItem *item = 0,
        const mudString &params = mudString::null);
}

void greetEvent::invoke(mudLiving *receiver, mudLiving *from, mudItem *,
    mudString &)
{
  // this will add command to the server command queue
  // the source of the command is receiver (first argument) and the command
  // itself is passed as the second
  server->addCommandToExec(receiver, "say to " + from->getName() +
      "welcome here, stranger"));
}

// time-based event is invoked globally, implement new one
class sayEvent : public mudLivingEvent {
  public:
    // standard constructor and destructor
    sayEvent() : mudGlobalEvent() {};
    virtual ~sayEvent() {};

    // like the above one
    virtual void invoke(mudLiving *receiver, mudLiving *from, mudItem *item = 0,
        const mudString &params = mudString::null);
}

void sayEvent::invoke(mudLiving *receiver, mudLiving *from, mudItem *,
    mudString &)
{
  server->addCommandToExec(receiver, "say i should say something right now");
}
These classes should be initialized somewhere. Obvious place for doing such thing should be module's constructor, where the action is created and events are added.
// include necessary header file
#include <mud_action.h>

// ...
// somewhere in module initialization cycle (module's constructor)
  // create events
  greet = new greetEvent();
  say = new sayEvent();
  action = new mudAction("custom");
  // for greeting
  action->addEvent("new living added", greet);
  // for saying
  action->addEvent("rt-tick", say);

// don't forget to delete created objects in destructor
Last thing that should be done is creation of living. Again, this place can be module's constructor. Living can be also completely defined by XML file, which describes such living.
// include necessary header file
#include <mud_living.h>
#include <mud_server.h>

// ...
  living = new mudLiving("Testing living");
  living->assignAction("custom");
  // rt-tick can be replaced by rt-minute, rt-hour or rt-day
  server->receiveGlobals("rt-tick", living);

// don't forget to delete objects :-)