The compleat hacker's guide to adding commands to the UnterMUD server: ---------------------------------------------------------------------- First off, figure out what you're trying to do, and see if there is a command that already exists that does something remotely like it. That's probably a good place to start. Take a look in the CMD directory, and at least glance through the various command modules. The first thing that should leap to your attention is that all the commands are called with the following interface: cmd_say(argc,argv,who,aswho) Where argc is an integer, argv is an array of string pointers, who is a string pointer and aswho is a string pointer. Basically, each command is VERY much like a little standalone UNIX program, having its own argc and null-terminated argv. In addition to that, there is the object-id of the caller ("who") and the permissions object-id of the caller ("aswho") in case the command is being called setuid. All you need to remember about "who" and "aswho" are the following three simple facts: 1) "who" is the person you should send all relevant output to. 2) "aswho" is the object-id you should use for all permissions related things, whatever they may be. 3) WHATEVER YOU DO, DO NOT MODIFY "who" OR "aswho", THEY ARE POINTERS OUTSIDE OF THE SPACE YOU ARE PERMITTED TO ALTER! Sorry to shout, but typically "who" may be a pointer straight back into some private buffer in the I/O layer, and if you skank with it, you've just literally changed the ID of the connected player. The argc and argv that are passed to each command are in private space somewhere in the stack, and you can feel perfectly free to change them, or re-point the argv[] pointers, if you like, as long as you don't overrun buffers and so forth. If you treat your argv/argc with the care that any sane person shows a UNIX argv/argc, you'll be OK. Anyhow, once you've figured out what you want to do, and looked at some of the other commands, now take a look at some of the code in objutil.c and maybe match.c - the idea here is to avoid replicating loads of code if you can. Small is good. The tricky decision comes when you're writing a command that will do a lot of modification to a bunch of objects. Using the higher-level functions in objutil.c may be a lot easier, but if you're going to make a lot of changes to a single object, or you're going to be doing something really trick, you may have to modify the object manually, by using cache_get() to get a pointer to it, then using objsetattr(), objattr() and so on, and then using cache_put() when you're done. IF YOU DON'T USE CACHE_PUT after YOU HAVE CHANGED AN OBJECT IT WILL NOT GET UPDATED. Sorry to shout, but that's important. If you just want to examine an object and NOT change it, you don't need to use cache_put() afterwards. If you wind up repeatedly performing the same set of operations on an object, think about the interface to that set of operations and try to make it generally useful and put it in objutil.c. No sense in having to make everyone else rewrite code. Next tricky bit: if your command requires access to internal data structures in either the network module, the cache, the db, or the main MUD server module, DON'T put it in CMD, put it in the module. This may be a pain, but it's necessary. If you write a TCP/IP specific command, it should be isolated with the other TCP/IP specific code. More importantly, WHATEVER YOU DO, DON'T DECLARE YOUR COMMAND IN ANY OF THE HEADER FILES. The idea behind UnterMUD is to make it easy to snap commands in and out, and having extraneous references to them will get you beaten to death with a tire iron. WHEN YOU CODE YOUR COMMAND, KEEP EVERYTHING STATIC TO THAT ---------------------------------------------------------- ONE FILE, OR YOU WILL BE SHOT. ------------------------------ Ok, so now your command, whatever it is, is written. Take a look at cmd.c and cmd.h and figure out how the Cmd struct is laid out. It's pretty simple, really. Then make a forward declaration in cmd.c, and an entry into the command table - please be so kind as to #ifdef them if you are not sure everyone's going to be dying to use your new command. Add the command file to the Makefile in CMD, and it'll be compiled into the library. If someone turns the #ifdefs on in cmd.c, suddenly your command will be a part of their environment. Please, for the sake of reason, try to do sensible things with command parsing inside your command - IE: don't use UNIX-like command flags in once place, and VMS-like slash delimiters in another. In fact, don't try to do command delimiters at all, if you can help it. It's my experience that tree-structured switches (see the "build" command, for example) are easier to understand anyhow. Besides, this is a game, not an operating system. It should be deleted before it starts to look like an operating system. TEST EVERYTHING THOROUGHLY BEFORE YOU DARE RELEASE IT. ------------------------------------------------------ mjr. '91