|
Phantasmal Site > Development > Old document
Sourceforge Development (legacy)
I consider everything here to be generally good etiquette for
doing work based on Phantasmal. These are only mandatory when
you're working with me specifically. But you may find that
they're good for your own work, too.
When you add a significant new feature, be sure to update the
documentation. At a minimum try to update the Changelog and add any
new appropriate online help. Other stuff to consider: new
tutorials, post what you did on the forums, update bug/feature
reports in the SourceForge tracker. Also consider adding it to more
than one Phantasmal game if it applies -- we've got both testgame
and the mudlib.
Where it's reasonable to do, try to make stuff update itself when
recompiled with the upgraded() function. This turns out to be
highly useful for things that read data files, such as the HELPD,
the various binders, phrase repositories and so on. Basically, make
a given entity reread its data files when you recompile it. That
keeps you from needing a command-line "@update_help",
"@update_phrases", "@update_mob_binder", etc command for everything
with its own data files. Instead, type "%full_rebuild" and you're
there. No muss, no fuss.
CVS Checkins
(to be updated, we use Subversion now)
- Make sure to do a "cvs update -Pd" before you check in
new files. Immediately before. This means you won't randomly blow
away other people's changes unless you actually mean to, and that
you can do a resolve easily on your own machine.
- Check in only files where you've made meaningful changes. The
roomfile and mobfile, for instance, don't need to be checked in
unless you've actually built something significant. The
bug-report and idea-report files normally shouldn't be checked in
at all. Don't include your character's body and mobile in the
roomfiles or the mobfile, either.
- If you add debugging print statements, log statements, driver
messages or whatnot, make sure you do it in keeping with the way
Phantasmal works now. Notice the current lack of any
DRIVER->message() calls after bootup, and how almost every
LOGD->write_syslog() call specifies a log level so you can
turn it off easily. Keep up that tradition.
- When you do your update, you'll notice which files in your
repository have been modified -- "cvs update" will show you this
stuff. Check it over again to make sure you checked in everything
you meant to.
- Never check in code that doesn't compile. For preference,
never check in code that breaks other people's stuff. It
really sucks to do an update and get code that won't let
you start up or won't let you run. And if you do that to other
people, you're stopping the whole project from getting any work
done. That's not friendly.
- Make your checkin comments meaningful and relevant. People
who read your comments and then look through the diffs on the
mailing list (I make sure to, and I'm probably not the only one)
should simply nod and say, "yep, that's the way to do what he
mentioned". If instead they find themselves saying "huh? That's
not what the checkin comment said," then you did it wrong.
- Check in your code a couple of files at a time, where
possible. Rather than checking in a huge swath of files at once
and giving a comment like "redesigned frobnication in c minor",
for a given couple of files, say something like "added new fields
to the DTD for mobiles. Added new parsing and UNQ code to make
them useful." The exception to this is if you've written and
checked in a design document detailing your changes in minute
detail, and that design document is expected to be available for
a long time. So you could check in a bunch of stuff and say "see
doc/design/frobnication_spec" and that'd be okay as long as
frobnication_spec spells out everything -- down to what files
changed in what ways.
- If you can't recall what you changed in a given file, "cvs
diff -c" is your friend. This prevents checkin comments like
"changed some stuff".
Bugtracking, Features, Tasks, etc
- SourceForge provides this stuff for a reason. You can work on
a bug/feature/etc without it having a formal tracker report, but
if you're going to be doing very much work you should enter a
tracker item if one doesn't already exist.
- SourceForge bug numbers aren't very recognizable. Still, if
you can you should mention the tracker number on any relevant
checkin. For instance, "Finished task #74094, object weight and
volume" would be a good sentence to see in a checkin comment. It
lets people find the tracker object unambiguously and get any
extra commentary you've been doing on the bug.
- Use the tracker. If you're working on a bug/task/feature,
assign it to yourself. If you change approach or fix it
differently than you expected, mention that in a comment in the
tracker.
- When you fix the bug, if you're feeling like a go-getter,
mention what files you changed, and possibly what the new
revisions of the given files are. CVS doesn't provide us checkin
numbers, alas -- they're a much better way to do this.
- If you finish a roadmap task, mention it to a project admin.
We keep a separate roadmap document updated and a number of the
tasks are mentioned there. We should remove them when those tasks
are completed -- they're done, so they don't belong on the
roadmap.
Inter-Object Security
- Upgraded() functions should be guarded by "if(SYSTEM())"
constructs, plus perhaps a guard for being called by the object
itself or its child objects. Create() functions should be static.
Destructed() functions should also be callable only by System
callers. In a library, the upgraded() and destructed() functions,
if present, should be static.
- Use the SYSTEM(), COMMON() and GAME() checks liberally.
Decide who should call a particular function and guard it
appropriately. The best, of course, is to specifically check
previous_program() so that only the expected caller can call the
function. Functions that only the current object calls should be
marked private.
- Every Phantasmal function should be one of: static,
private, checks previous_program(), or documented to say exactly
why not. The only functions that don't need to be
access-protected are utility functions like the ones in STRINGD
that have no access to any Phantasmal data. They can exist, but
you should document why anybody is allowed to call them.
- Never call anything in a publicly writable directory. Never
call a method of any object in a writable directory if you don't
trust all possible writers. Remember who has access to what.
Remember that if a directory is writable by a given object, that
object could have overwritten the file and recompiled the object
while you weren't looking. Don't trust it.
- Never pass your internal data structures to the outside world
without copying. The caller may not realize that the data
structure is sensitive to you. Always copy it first so that you
don't have to trust the caller not to modify it.
- Never gratuitously add callers without reason. Sure, you may
trust "common", but why give it specific access to something it
doesn't need? You should know who calls a function. Give them,
and only them, access.
Adding Commands
- Add an entry to the online help for that command
- Add the command to "/data/phrase/user_cmds.unq",
"/usr/System/obj/wiztool.c" or the equivalent.
- Add the command's associated function to the user object or
userlib, or one of the wiztool libraries in
"/usr/System/lib/".
- Make sure the command checks usage. See one of the existing
commands for how to do this. If it's used improperly, it should
print a message saying so.
- Make sure the command gives status messages to the user
object that called it. Then if there's an error midway through,
the user will know if it succeeded properly. That way you don't
have to be subscribed to the error channel to know that an error
occurred.
- Players and administrators need to have a good example of how
to use the command. A Tutorial is an appropriate way to handle
this for administrators.
- Mention in the Changelog that you added the command.
Adding New Types of Objects
- If a user or admin can see them or manipulate them in any
way, physically or with any command, add them to the online
help.
- Make sure that their code can be upgraded when the file is
recompiled, to the extent that you can.
- Objects should save and load with %datadump and %shutdown and
stuff. If they don't, they should either be entirely made of code
(no data, no data structures) or have some other serviceable way
to save and load. Requiring %reboot is not an acceptable
way to save and load, it must be possible for objects to
survive a %shutdown.
- Objects should survive a %shutdown and reload as near to
unaltered as possible. They should behave the same way before as
after. Seriously.
- If these new objects can be created or manipulated by users
or administrators, we'll need web documentation. Submitting a
Tutorial would be a great way to handle this for admin commands.
You could also submit API docs.
- Mention in the Changelog that you added the objects and any
commands that deal with them.
Adding Fields to an Object Type
- Add commands to manipulate the field -- see "Adding Commands"
for further details. There should always be admin commands in the
wiztool for the fields, and there may be user commands as
well.
- Add get and set functions for the new field to the object
it's a member of. If there's a document for that object in
"/doc/api", add documentation for those functions.
- Add the field to the object's UNQ DTD. Add it to the object's
UNQ read and write functions. This only applies to fields that
need to be loadable and saveable.
- If the field may need to be set for common objects, add it to
the MAKE_ROOM user state. Make sure the field is prompted for
only when appropriate, and that it behaves reasonably for
portables, rooms and details.
- If appropriate, submit a Tutorial that covers the new field
and how to use it.
- Mention in the Changelog that you added the field.
|