Dbref
A dbref is a number that uniquely identifies an object at a given point in time. That is, at any given moment, any given dbref refers to a single object or to garbage, and each object has a single dbref. Dbref is short for "database reference".
Dbrefs are written with an initial # (hash mark or pound sign), begin with #0, and increase as more objects are created.
Some dbrefs are typically provided in the minimal startup database and considered "special", including:
- #0 is typically a room and serves as the base_room from which connectedness is tested.
- #1 is typically the dbref of the God player.
- #2 is typically the dbref of the master room for global commands and exits.
Because dbrefs are recycled when objects are destroyed and new objects are created, it is possible for a given dbref to refer to different objects at different points in time. This can create a problem when softcode does permission checking based on a list of dbrefs and one of the objects on the list is destroyed without removing it from the list. In PennMUSH, this problem can be avoided by using an object's objid instead of its dbref.
Server Differences
On TinyMUX, the test for floating rooms starts from the player_starting_room. Also, the initial database contains just Limbo (#0) and Wizard (#1). However, the Sandbox Globals Project (SGP) minimal database included with TinyMUX does use #2 for the master room.
Poor Usage of #dbrefs in Softcode
Often designers of softcode make the assumption that once a #dbref used by an object, it will always be used by this object. However, often players and objects will be deleted, recreated, replaced, etc.
Nifty trick
So how do you know if the object referenced in the past is the same in the present? By combining the #dbref with a timestamp and possibly other information.
PennMUSH already has a builtin function called objid() to do this, however MUX does not. This can be easily softcoded with some different behavior:
&f.objid functions object=default(%0/_objid,set(%0,_objid:[setr(0,num(%0):[secs(,3)][rand(100000)])])%q0)
Such code assigns an object id on the fly if the object does not already have one. Otherwise, it simply grabs the object id out of the _objid attribute. (Attribute names prefixed with an underscore (_) are dark and wizard on MUX, see attr_access)
Finding the #dbref of an object from its object ID is fast: before(%0,:)
Instead of reference objects by #dbrefs, objects can now be referenced by their object ID with one additional function:
&f.objidnum functions object=case(xget(before(%0,:),_objid),%0,before(%0,:),#-1)
This works like num(), but it takes an object ID as its first argument instead.
--Ian