ref1: Core Java, Vol 1, Java SE 6
Understanding the Recursive Room Loader
The initial map, items, and monsters are all loaded
once by MudMain::initialize(). This function is called by the
RDS Kernel (I believe) to launch the application. It is passed the Properties
filename that was in the *.boot file equated to
in the case of this game. The Property map file is a string based key::value
pair file. These are normally used for storing user preferences
for an application. But they can be used for just about any thing needed
a key::pair structure. The New Room file talks
about the structure being used by this game.
After some setup, the initialize() method
calls loadRoom() and sends it the Properties filename and the
name (key) for the first room. This is a lookup process, so the file does
not have to be in any particular order. I have grouped the key::values
that are associated together though.
loadRoom() is an overloaded method. The
initial one starts and ends the recursive process. It builds up a HashMap
to store the Rooms as they are found. This allows other Rooms and Doors
to use the information when needed.
The more complex loadRoom() does the real
work. It is designed to be re-entrant and uses four parameters:
nameNT - the name of the next room to look
properties - the filename of the properties
from - the last room/door found that is
looking for this room. Use for error messages.
lookup - the master lookup HashMap for
storing rooms found.
The first thing it does is trim the nameNT String to get rid of white
space before and after the string.
It then checks to see if this named entry has a class reference. It
sets the class to the name of Room.class which would be com.sun.sgs.darkmud.core.Room
for this game unless there is a .class property for nameNT. Note,
the nameNT for the first room searched for is "room.origin".
The next thing is to look for a name.aliases property. If
one is found, the .split() operator is used to parse the property String
into a String[ ] array using a comma as the separator as shown in the regex
passed into .split().
A Room reference is then setup and set to null. It the attempts
to generated a new MudObject of the requested class and provides the aliases
for the object as well by calling newMudObject().
The two newMudObject() end up returning a MudObject of a Template
using the class requested. this somewhat complex way of doing thing allows
you to declare the class as a property string or that's my assumption.
What it boils down to is that MudObjects are made by passing an array of
aliases to the constructor which are then stored in a HashSet list member,
aliasList, of the MudObject.
NOTE: The is no requirement for an object to have aliases.
Next the room's description is read in. All rooms should have descriptions.
The room's setDescription() method is called to store the description
in the room object.
NOTE: A future change will be to add long descriptions for rooms.
As this point, the room is stored on the lookup list using the name
as the key and the object as the value.
Now the inventory of the room is loaded using the String.split()
operation as before and sets up a String[ ] array of names.
Inventory objects can be Doors or Items. Items can be anything that's
not a door (a passageway) or room (an area) like NPCs, objects, sounds,
A Door is Found in Inventory
Assuming that a Door name is in the array, the loadDoor() method
is passed the item's name, the properties filename, the name of the room
it is in, and the lookup list so that it can be added for future reference.
As with the Room, the Door class is first set up. If no class property,
then Door.class.getName() would return com.sun.sgs.darkmud.core.Door
for this game.
Then the aliases are collected and the normal and long descriptions
are read in.
Unique to Doors is the direction string name. If there is no direction,
then the direction is set to "nowhere". So you access a door without a
direction by using "go nowhere"? Strange.
The next thing is to load the destination for the Door. Doors can only
go to one place, for now anyway, and the destination has to be a Room object.
Now for the recursive part. If the Room name is not on the lookup list,
the loadRoom() method is called to load the Room and this can
cause use to go through the whole process again.
If this is a good Door that leads to a Room that exists, then create
a Door MudObject of the proper class and save the descriptions, direction,
and destination room into the Door object.
All done, so return the Door object to the Room caller.
One thing to note, Doors don't have inventories. This could be an area
for improvement as keys could be left in doors or special items used to
Final Step for the Room
The valid Door object is added to the Room's inventory and after all of
the inventory items have been added, the Room's name is bound to the Room
object to be handled as a ManagedObject by the database.
An Item is Found in Inventory
Items are handled similar to Doors. The loadObject() method is called
and passed the item's name, the property filename. and the name of the
container (the Room normally).
As with the Rooms and Doors, the class property is checked for and
com.sun.sgs.darkmud.core.MudObject is used if no class is set.
The aliases are then gather up and the object is created and the descriptions
added to the object.
The last step leads to recursion again since Items can have Inventories.
Each name in the inventory String[ ] array is turned into an object and
added to the Items inventory though a call to addToInventory()
and passing an object returned from a recursive call to loadObject().
So, you can have bags within bags. Guns with clips and clips with ammo,
That's it in a nutshell.