Anatomy of a LambdaMOO db file Authors: Robert Leslie , Alex Stewart Disclaimer: Messing with the internals of LambdaMOO db files is inherently dangerous, and is not recommended. The following information is to be used at your own risk. The db file is flat ASCII text organized into lines. The first four lines comprise a header of: the total number of objects in the database, including recycled objects (also the value of max_object() plus one); the total number of verb programs in the database, not including unprogrammed verbs; a number whose value is uninteresting, and the total number of objects whose player flag is set. The next N lines comprise a list of player object numbers. N is equal to the value of line 4 in the db header. The next section contains a description of every object in the database. Each object has the following structure: a tag line containing a pound sign and the object number. If the object has been recycled, the word "recycled" also appears. For non-recycled objects: a string containing the value of the object's .name property; a string which can be ignored; a number containing a set of flags, described below [1]; the object number which is this object's .owner; the object number which is this object's .location; the object number of the first object in a linked list of this object's .contents (or -1 if it contains nothing); the object number of the next object in a linked list of this object's .location's .contents (or -1 if the end of the list); the object number of this object's parent; the object number of the first object in a linked list of this object's children (or -1 if it has no children); the object number of the next object in a linked list of this object's parent's children (or -1 if the end of the list); the number of verbs defined on this object, regardless of whether they have been programmed; For each verb: a string containing the name(s) for the verb; the object number of the owner of the verb; a number containing permissions flags, described below [2]; a number containing an argument preposition code; The next line contains the number of properties defined on this object, N. Following this are N lines of strings containing the name of each property. Finally, values for all of this object's properties are stored. The values are ordered sequentially, first giving values for each of the properties defined on this object, then values for each property defined on this object's parent, then for the parent's parent, and so on up to the top of the object's ancestry. The first line contains the total number of property values which follow. For each property value: a number indicating the typeof() of the datatype, or the number 5 to represent a clear value; For non-clear values: for a string datatype, the contents of the string; for object, error, or number datatypes, the value as a number; for lists, the length of the list, N; For a list value, N more data definitions follow (one for each element of the list) in the same form (integer type followed by appropriate additional data.) Finally, each property value is followed with: the object number of the owner of the property (on this object); a number containing permissions flags, described below [3]; Following the object descriptions is verb program code for every programmed verb. Unprogrammed verbs are omitted. For each program: a tag line containing a pound sign, the object number where this verb resides, a colon, and a zero-based index into the object's defined verbs specifying the verb associated with the following code. The program code for the verb follows, in source form. The code is terminated by a single dot. The last section of the db file contains suspended task information. The first line in the queued tasks list is of the form " clocks" (where is a number. This is basically an obsolete aspect of task handling in the earlier days of MOO servers, and is simply reported as "0 clocks" in modern servers. If nonzero, it's followed by lines of clock data which can be ignored anyway. Following this is a line stating " queued tasks", which is the number of forked tasks in the task queue. Following this are blocks of data containing the state of the MOO for each task, defined variables, and the portion of verb code being executed. Each of these blocks starts with a line of the form: 0 Followed by two more lines which don't mean anything anymore: 0 -111 Followed by a line of the form: -7 -8 -9 -10 (the -7 -8 -9 and -10 spots aren't used for anything anymore) Followed by 4 more unused lines: No More Parse Info followed by the value of the "verb" variable at the current point in time, followed by the name of the actual verb that goes with the verb code being executed. Next comes information on the runtime environment (variable definitions), then the block of verb code that was forked off, ending in a line with a period by itself. After all the forked tasks comes a line of the form " suspended tasks", which is followed by blocks of info for the suspended tasks. While I could go into great detail about the contents of the file from here on it probably wouldn't do many people very much good, as it's nearly impossible to follow all the little details by hand anyway, and I'm not sure why someone would want to for suspended tasks.. If you're just looking through and want to know what you're seeing, there are blocks of data (one for each task). Each of these blocks has data for each point in the callers() stack (in the order of first-executed (shallowest) to currently-executing (deepest)). For each entry in the callers() stack, it lists the verb code of the executing verb, all of the variables defined for that invokation, a block of data similar to that listed for forked tasks (0, -111, this/player/etc line, "No", "More", "Parse", "Info", verb, verb-name), and some other less informational stuff stuck in here and there between them all.. And then there is the end. [1] Object flags: player 0x01 programmer 0x02 wizard 0x04 read 0x10 write 0x20 fertile 0x80 [2] Verb permissions: read 0x01 write 0x02 execute 0x04 debug 0x08 dobj arg 0x30 ("none", "any", "this") iobj arg 0xC0 ("none", "any", "this") [3] Property permissions: read 0x01 write 0x02 chown 0x04 Answers to Common Questions How do I find a particular object? Search the db file from the beginning for the string "#X" on a single line where X is the desired object number. Of course, you might find instead an object string property value which happens to contain the same text, so be sure you also check the following line, which should contain the name of the object you're looking for. How do I remove/add/modify properties? Adding or removing properties is treacherous; property definition counts and value counts must match exactly, and you must take into account property values on all descendents of the object in question. You might be able to get away with modifying the value of a property if you're very careful. It might be hard to find the actual value in the db file, since it isn't obvious which values are matched with which property names. If the current value is something you could search for (say, if you knew an encrypted password beforehand and could search for it) you might have better luck. How do I remove/add/modify verbs? Removing verbs is easier by comparison. You must delete the four lines containing the verb definition in the object description where the verb lives, and decrement the verb count on the 12th line of the object definition. If the verb has been programmed, you should also remove the associated verb code in the latter portion of the db file and decrement the global verb count on the 2nd line of the file. There is one gotcha: by removing the verb, all later verbs in the object have been renumbered (recall the verb code section assigns code to verbs using a 0-based index) so you must renumber the tag lines for the affected verb programs accordingly. It would be feasible to add a new verb by doing the reverse of this. How do I remove active tasks? You could eliminate all suspended tasks by replacing the last section of the db file containing task information with the following three lines: 0 clocks 0 queued tasks 0 suspended tasks These lines should immediately follow the last verb program, and should be followed immediately by the end of file. Are there any rough integrity checks I can perform by hand? The above description is probably complete enough for you to decide whatever integrity checks are feasible and how to make them. However, testing a modified db with the real LambdaMOO server is probably the best way to be sure it is still at least usable. If there are minor problems, the server may even be able to compensate for some of them during its own rigid verifications. I shouldn't need to emphasize that editing db files by hand is inherently dangerous. I really don't recommend any amount of significant hacking. Also, although I am fairly confident the above description is correct, I am by no means making any guarantee about its accuracy, and certainly am not willing to accept responsibility for any damage done to anyone's db as a result of my making this public. Nonetheless, I hope it's useful to some.