Phantasmal MUD Lib for DGD

Phantasmal Site > DGD > Writing a Library

Writing a MUD Library for DGD

Actually, all advice here applies just fine to writing general DGD applications, but there's certainly a focus on writing a MUD-type networked game.

If you decide to use the Kernel Library, you should definitely read Getting Started with the Kernel Library.

Choosing a Starting Point

Tutorials and Simple Issues

Large or Major Design Issues

Subtle Driver Issues

Things in this category require significant understanding of how DGD does things. They're either subtle issues that you can (usually, mostly) ignore, or they're interesting ideas that require significant understanding to implement.

Philosophical Issues

Specific Components

This section is about how to implement specific services or systems within DGD.


From: DGD Mailing List (Felix A. Croes)
Date: Sun Apr  4 17:47:01 2004
Subject: [DGD] DGD-Fishing

Ragnar Lonn wrote:

>[...]
> Speaking of that I'd like to thank Felix for the pointer to the extensions
> document. I'm not sure extensions is useful for what I would like to do
> (I'm interested in e.g. replicating objects between two DGD instances) but
> I realize I have some reading to do.

Replication of objects can be managed without DGD hacks.  Here is an
outline of how I would do it:

To completely replicate an object you must have its source code, a list
of objects it inherits from, a list of the variables it declares, and a
way to query and set those variables.

At compile time, parse the source code with parse_string() using a LPC
grammar to learn the objects it inherits from and the variables it
declares.  Temporarily append functions to the source code which
query and set those variables, actually compile the object, and
restore the original source code.

One difficulty is the preprocessor.  Somehow you have to deal with
macros.  This can be done by writing your own preprocessor (again
using parse_string()), but since the preprocessor is no doubt the
ugliest part of the LPC language, and since you are pre-parsing the
source code anyway, I would suggest forbidding the use of any
preprocessor commands except for #include, and adding constants to
the pre-parsed language:

    const int foo = 1;

Your parser accepts these and replaces them with #defines.  Constants
are the only essential feature provided by the preprocessor, everything
else can be replaced by normal code (and this will probably make the
LPC code more readable as well).

Replicating objects in this way would work for different DGD versions.
Of course you would have to fix the grammar if the language changes,
but the LPC language changes very slowly compared to the rate at which
DGD's internals change.

Of course, it is possible that you want to do more than replicating
objects, and that some of those other things cannot be managed through
LPC. :)

Regards,
Dworkin

From: DGD Mailing List (Michael McKiel)
Date: Sun Apr 25 02:04:01 2004
Subject: [DGD] RE:time() and suspending call_outs

 --- Steven Brooker(Immortius) wrote: 
> What's wrong with saving them to file somewhere?  My
> objectd copies the code into ./current after compiles.
>    You just need to make sure people can't compile the
> contents of these backup folders.
> 
I believe Erwin was referring to what Dworkin does in his mudlib, he keeps
the source code for compiled objects, and can access/dump the source to a
file, and compare differences between various versions of compiled objects. 
Sounds like yer talking about a non-automated process, and done by hand.
Which if you want to keep source like that then likely not much issue, aside
from the fact that you have to recompile all objects using that source,
instead of having some that are based off of different source.

From: DGD Mailing List (Par Winzell)
Date: Tue Mar 23 11:50:02 2004
Subject: [DGD] Re: casting nil (another idea...)

> I'd go for something like this:
> 
>     int nil_to_int(mixed v)
>     {
> 	return v == nil ? 0 : v;
>     }
> 
>     ...
> 
>     luck -= nil_to_int(query_property("luck_reduction"));
> 
> If you put the nil_to_int() in an inheritable it doesn't look so bad?

For every library that I've worked with in the past many years, I define 
  Int(), Str(), Arr(), etc, something like nil_to_int() above. Also 
useful is a Empty() macro/function that returns true for nil, empty 
strings, empty arrays, empty mappings, integer zero, ...

Zell

From: DGD Mailing List (Robert Forshaw)
Date: Tue Jan  6 15:27:00 2004
Subject: [DGD] About runtime errors

I examined Kernel's method of dealing with runtime errors, left feeling more 
confused than before and decided to write my own function by trial and 
error. This is what I've ended up with:

void runtime_error(string error, int caught, int ticks)
{
	mixed ** trace;
	mixed * err, err2;
	trace = call_trace();
	err = trace[sizeof(trace) - 2];
	err2 = trace[sizeof(trace) - 3];

	message("\nRuntime error in function " + err[2] +
		"()\nIn Program \"" + err[1] + "\" on line " + err[3] +
		",\nWhich was called by \"" + err2[1] + "\" via " +
		(err[4] ? "call_other()" : "inheritance") +
		"\nwithin function " +
		err2[2]  + "() on line " + err2[3] + ".\n");

}

This seems to produce the correct output. It always assumes that the last 
element of trace describes the current calling process, that would be 
runtime_error(), and before that the erronous function call, and before that 
the program and function which called the erronous function call. Is there 
any situation where this might not be the case? In other words, is this 
function fallable, or even downright incorrect...?

Could someone explain to me what a 'full stack trace' is exactly?  :)

Date: Tue, 29 May 2001 03:53:37 +0200
From: Erwin Harte
Subject: Re: [DGD]IP to alphanumeric

On Mon, May 28, 2001 at 07:56:54PM -0500, Lord Lerkista wrote:
> 
> On Monday, May 28, 2001, at 07:33 PM, Erwin Harte wrote:
> 
> > You might want to have a look at the query_ip_number() kfun.
> 
> I try with query_ip_number() and query_ip_name() and both returns the 
> numeric ip!!
> =/

Three options:

1. Your machine doesn't have name-resolving configured properly.
2. The query_ip_name() kfun is redefined by something that doesn't work.
3. Perhaps the ipnumber doesn't resolve correctly.

The example ipnumber you gave resolves just fine though, so 1 & 2 are
the only reason I would put any money on right now.

Good luck figuring it out. :-)

Erwin.
-- 
Erwin Harte

From: DGD Mailing List (Erwin Harte)
Date: Tue Jan  6 12:37:00 2004
Subject: [DGD] Re: A simple lib

On Tue, Jan 06, 2004 at 06:27:29PM +0000, Robert Forshaw wrote:
> >From: "Felix A. Croes"
[...]
> >driver::telnet_connect() recompiles /sys/user every time, that's probably
> >not what you want.
> 
> I understand that it isn't what I want. The only reason I have it like this 
> is due to 'tweaking', i.e. I'm making sure it isn't the clone() function 
> I've defined that is the problem. My clone() function is OK, right?

No.  You want something like this:

    object clone(mixed file)
    {
	    object master, clone;

	    if(typeof(file) == T_STRING)
	    {
		    message("Type is string.\n");
		    if(!(master = find_object(file)))
		    {
			    master = compile_object(file);
			    message("Compile object successful.\n");
		    }
		    clone = clone_object(master);
		    message("Clone object successful.\n");
		    return clone;
	    }
	    return clone_object(file);
    }

The reason is that compile_object(file) on an already compiled object
will quite happily compile it again (only failing if the object has
been inherited) and you can't do that more than once in a single
thread, which is exactly what your current clone() function in
sys/driver.c attempts to do.

    object clone(mixed file)
    {
	    object o;
	    if(typeof(file) == T_STRING)
	    {
		    message("Type is string.\n");
>>>>		    if(o = compile_object(file))
		    {
			    message("Compile object successful.\n");
>>>>			    if(o = clone_object(compile_object(file)))
			    {
				    message("Clone object successful.\n");
				    return o;
			    }
		    }
	    }
	    return clone_object(file);
    }

Hope that helps,

Erwin.
-- 
Erwin Harte

From: "Ludvig Lejon"
Subject: Re: [DGD] DGD Commercial Licensing?
Date: Wed, 22 Sep 2004 12:05:39 +0200


----- Original Message -----
From: "Stephen Schmidt"
To: DGD List at imaginary.com
Sent: Wednesday, September 22, 2004 4:38 AM
Subject: Re: [DGD] DGD Commercial Licensing?


> On Tue, 21 Sep 2004, Jas wrote:
> > Why not pre-install most of the image files on the player's PC, much the
> > same as Everquest and other games like that are doing?
>
> The problem is wizards writing new areas. This works under two
> circumstances:
>
> 1) You can pre-install a wide enough range of images that wizards
>    can code new areas using only the existing image files.
> 2) You abandon the traditional wizard-codes-area scheme.
>
> I'm pretty skeptical about #1; I think if you go this road you
> are looking at #2, limiting the extensibility of the game world
> in some way (or requiring all users to upgrade their image
> libraries periodically and having new areas be inaccessible
> to players with outdated versions).
>
> That said, I have no experience with anything like this, and
> obviously other people do, so there may be incremental
> solutions (rapid and reasonably transparent updating of the
> image lib, maybe) which would work around the problem.
>
> There is also the problem of having the wizards create new
> images, and having the admins check them for appropriate
> content, and so forth, but those problems are no different
> in nature from what we face with wizards writing new text.
>
> Steve
>

Well, I think this problem could be solved quite nicely.
Let's say you build a world and place all images required in the players
client.
When a new built area is access by a player, the server asks the client if
that area's images is availible on the players local hard drive.
If not, they are downloaded to the client while the player sees a
"Loading"-screen.
The same goes for weapons, new monsters around the world too. The server can
easily just ask the
client if the required images are already downloaded, if not a download
procedur is started.

I think my solution will be much more appreciated amongst players than the
solution where they have to manually update their clients.

Lejon