[MUD-Dev] An Idea... Mud Development Framework

Bruce bruce at puremagic.com
Sun Jan 14 02:32:52 CET 2001


Hiya Jeremy,

Jeremy Lowery wrote:
> <EdNote: Duplicate HTML copy deleted.  Formatting
> cleaned up.  I'd much rather you did this than me.>

(And I keep having to reformat what I'm replying to in order that
it might hopefully line-wrap correctly.)

<EdNote: bow>

>   MDK (Mud Development Kit)
>   Jeremy Lowery
> 
> Purpose
> 
> The MDK's purpose is to provide a scriptable object-
> oriented MUD developing environment.

What is your intent here when you say 'scriptable'?

Do you mean that you want end users to be able to modify the
behavior of the system without having to learn a complicated
programming language?

Or, do you mean that the code should be able to be modified at
runtime?

Or, do you have another meaning entirely?

> The MDK Framework
> 
> The MDK system is the framework that is used to develop
> muds. MDK implements a class-object hierarchy, design
> patterns, and polymorphic data-types to support the
> extensible nature of the development environment (DE).
> 
> The Object Factory
> 
> The object factory manages all objects created in the
> DE. The factory also includes built in support for object
> serialization via standard C++ file streams. The factory
> maintains the file structure of all game objects internally
> in a special resource file named ofrdb.mlib (object factory
> reference database). The factory also needs to keep track of
> all objects created in the game. This is accomplished by a
> unique virtual index number assigned to every single "thing"
> created in game (all of which are objects).

That sets an initial assumption that you'll be working in C++. 
Are these objects C++ objects, or some construction of your own?

What happens when (not if) someone puts the wrong data into
ofrdb.mlib?

What are the virtual index numbers used for? (Why are they
virtual?)

Can you have multiple object factories?

> Advantages include:
> 
>   a.. Item copying identification

What is this?

>   b.. System Snapshots

How will you go about maintaining the integrity of the data and
insuring that a snapshot is a fully consistent view of the data
at that point in time?

> The Notifier
> 
> The object notifier is a singleton object that processes
> and dispatches object-based messages. Based on the message
> scope and type, the notifier dispatches the message to the
> corresponding target object(s). The notifier also has built
> in security features that allow message destruction before
> processing for invalid message usages. The notifier and
> object factory work closely together to handle object-
> creation and message dispatching. Indeed, they share the
> same object pool.

Why is there only one notifier?  What happens in the event of a
distributed system or a cluster of servers?

What type of security features are these? Is this at the
scripting level or the C++ level (or both)?  If at the C++ level,
how does the C++ code get information about the environment
within which it is running to make security decisions?  (I'm
thinking about MOO with its task-based security system and
ColdCore which has a system of primitives upon which you can
build an object-based security system.  I'm not aware of many
other security systems in the MUD world.  There is some
interesting stuff out there like the work on E
(http://www.erights.org) and some work based on the Lambda
Calculus (http://mumble.net/jar/pubs/secureos/secureos.html).

> Game Messages
> 
> Object interaction is achieved by using the notifier. All
> objects must override member functions that parse system
> messages directed to them by other objects.

There is no way to have a message bound to a bit of code (like a
method), or do I misunderstand what you mean when you say
'parse'?

> In addition to simple object messages, the DE also
> supports message scope resolution for message sending
> objects. These specifiers can be used to send messages
> at a certain game-level scope (More on this a little
> later). All messages are identified by a unique integer
> constant abbreviated MM_ (for mud message). Associated
> with messages is a generic message handling data-type
> identifying message specific data. Unlike most MUD systems,
> the MDK does not explicitly bind client messages to
> character objects. One of the main advantages this
> approach exposes is the use of a common socket-polling
> connection for every kind of game manipulation that is
> possible. Aside from characters playing the game, this
> also allows administrators, builders, and developers to
> have parallel game access, but via different interfaces.

I'm not sure that I understand much of the above paragraph.

> System Messages
> 
> The framework can also send messages to game objects.
> Unlike game message, system messages know no boundary.
> Of course, it is the object's responsibility to actually
> do something with the message. Common examples of system
> message include time messages, shutdown messages, client
> disconnection, and persistence messages (i.e. messages
> that tell objects to save themselves on a regular basis
> incase of system failure).

Is there any default handling for some of the messages, like the
one directing an object to save itself?  If not, wouldn't this
have the negative effect of distributing the knowledge of
handling data saves through out the code?

For some thoughts on that topic, check out a post by Miroslav
Silovic,
http://www.kanga.nu/archives/MUD-Dev-L/2000Q2/msg00060.php

> The Network
> 
> One of the only things that need to be hard-coded into the
> system is the actual game server. Of course, in reality

I'll take exception with the concept of 'hard code' later in this
post.

> it is just another object. It sends messages to other
> objects and receives them just as any other object does
> (via a method called message/object pooling discussed
> later). Not only does the network processes in route
> messages, it also binds client connects to game objects
> (mainly characters). The network then dispatches the
> messages to the object with a special client-specifying
> message. Although this can also be manipulated to include
> other objects such as items or rooms (not just characters).
> All objects that can be manipulated by clients exposes a
> command interface that is used for client manipulation.
> Scripts to manipulate the objects programmatically can
> also use this interface. For example: the Mobile object
> exposes a message-handling interface that includes a talk
> command. In a script, a NPC can use the exact same
> speaking interface that players use to communicate.
> 
> Client-Binding
> 
> All clients must always be binded to some object that
> exposes a command interface. Even if this object is not
> an in-game representation of something (such as a
> character). Other interface objects may include a
> character loader object, a shopping object, or a
> menu object.

I've come to like how Cold handles this and will be doing
something similar in my current server efforts.

Cold lets you assign a connection to any object.  When there is
incoming data, it calls the 'parse' method on that object.  From
here on out, it is up to the core to set the policy for what
happens and how that input is handled.

ColdCore builds upon this by providing $connection objects which
handle the actual connection, but which delegate all input to an
instance of an object that implements the $connection_interface
interface.  For something like a login screen, there is an
instance of $login_interface.  Once a user has logged in, the
object that the $connection delegates to is changed to
appropriate user object, which happens to implement the
$connection_interface interface.  This allows us to handle many
other networking tasks, like SMTP, HTTP, POP3, etc simply by
implementing specialized interface objects that understand that
protocol.

> ... Stuff snipped ...

> The Life of an Object
> 
> Generally, all objects live the same life inside the
> program. They are created by the Object Factory, load
> their data from disk, sit around processing messages,
> and eventually die. Of course, the most interesting
> part is the message processing. All objects are inherently

I don't know .. I think that the 'eventually die' part of the
object lifetime is Very Interesting.  How do you know when an
object can die?  How do you handle lingering references to
it/dangling pointers?  Do you explicitly manage the lifecycle of
objects?  Use refcounting?  Full blown garbage collection?


> ... Much snipped ...

I disagreed with a lot of what I snipped, but there wasn't any
simple way to explain why apart from my holding a different set
of beliefs.

As I said above, I'd explain why I don't like 'hard code'.  There
are servers around which are almost entirely in 'hard code'.  Any
change requires a reboot, but the whole thing is pretty much
written in a single language.  However, they aren't very
extensible during runtime.

There are another class of servers which implement a 'driver' or
the base server, like Cold, MOO, Muq, and DGD.  On top of this, a
mudlib, or core is written which implement the actual game.  The
driver provides a set of abstractions and a set of interfaces
with which the core can communicate.  Over time however, it seems
that the evolution has been to move the boundary lower and lower,
so that less and less policy has been hard coded within the
driver and more left up to the core.  Also, there are typically
at least 2 implementation systems used when working with one of
these systems.  The basic driver is often written in C, while the
core is written in a custom language provided by the driver
(except in Muq's case, where Muq lets the core provide
assemblers, so that many languages can be supported).

In working with Cold, as I've needed to do more and more complex
things, I've often needed to lower the boundary even further so
that the driver was deferring to the core more, but
unfortunately, it was in performance critical areas, and doing so
wasn't entirely possible due to the inability for the driver to
call into the core and get back a result.

To solve this problem and others, I wanted a system that didn't
have a 'driver' or a 'core'.  I didn't want to have to switch
languages depending on which level I was working at.  I wanted to
be able to soft-code things to prototype them out and then
'convert' them to 'hard code'.  I want to see a new type of
server where you can work in the same language from the ground on
up, accessing the same object model.  Ideally, I'd be working in
an interpreter for that language to prototype while the server is
running, and then have a mechanism for compiling code that native
code to be linked into the server for greater speed.  Because
there is no boundary between 'driver' and 'core', but only a set
of libraries which comprise a server framework, there aren't
arbitrary boundaries to work around in setting up low level
elements of the system.  I'm on the path currently towards
creating such a server.

 - Bruce
_______________________________________________
MUD-Dev mailing list
MUD-Dev at kanga.nu
https://www.kanga.nu/lists/listinfo/mud-dev



More information about the mud-dev-archive mailing list