Jamie Cameron
Supervisors : Lloyd Allison and Jon McCormack
7th November, 1995
The system allows users to move about, communicate and interact with the world and each other. As the world can be distributed over multiple servers, the system scales well as the virtual world size increases. Worlds are specified using a number of simple text formats, and so can be easily created and modified.
My overall design was for a client-server system, in which servers store and
control the world, and clients are run by users to interface with that world.
One world might be split over several cooperating servers on different machines,
and users would connect the server responsible for the part of the world
their avatar is in. If an avatar crosses the boundary between one server's part of the world another, the crossing is transparent to the user. The old server contacts the new and transfers full details of the avatar across, then directs the controlling client to connect to the new server. If the world is properly designed, all the user should notice is a short time delay for the transfer to take place.
In my design, each server is responsible for and controls everything within its part of the world, known as its map. If a user gives a command to do something (like move, communicate or pick up an item), then a request is sent by the user's client program to a server. The server validates the request, and if valid sends the results to all other clients connected to that server. Thus even if a user has modified a client program to 'cheat' in some way (for example, allowing arbitrary movement or teleportation) the server will detect and ignore such requests. In my design, the server program regards all data from clients as possibly untrustworthy and in need of validation.
When a user's client program connects to a server, that server attempt to locate the user's avatar in the virtual world. If the avatar cannot be found, then it is assumed that this is the first time this user has entered the world, and an avatar is created on the server initially connected to. If the user's avatar is located, then the client is redirected to the server responsible for the part of the world in which the avatar was found.
Once a client program knows which server its user's avatar is on, it connects to that server and receives data on the state of that part of the world. The connection is kept open for sending requests and receiving commands to and from the server. The connection is broken only when the avatar moves to another server or the user exits his or her client program.
When a client program connects to a server, it provides a name to identify the avatar of its user. Because the user chooses which name to use, a user could 'take over' another user's avatar simply by providing its name. To prevent this, I designed the system to optionally associate a password with each avatar. A user can choose to assign a password to her or his avatar, and from then on all users connecting with the name of that avatar must supply the password.
Data associated with objects can be used for a variety of purposes. Below are some examples used in the world I created for this project.
This client runs on Unix workstations with the X11 window system.
The user interface is created using the JX gadget toolkit,
and the 3d graphics handled by the s3dt library. The
s3dt library is a simple toolkit for creating and rendering
3d shapes that I created for this project. It provides adequately
fast 3d rendering of moderately complex scenes using Z-buffering
[7] on any Unix system with the X window system.
This client is almost identical the the X11 3d version, but uses
SGI's Inventor [8] 3d graphics library for
rendering and managing scenes. The Inventor library makes use of
the fast hardware support for 3d graphics on SGI machines, and so is only
available (at present) on these systems. The main advantages of this client
over the s3dt version are faster rendering and support for
texture-mapped shapes.
The text client provides a simple command based interface to the
world, suitable for users with dumb terminals or slow machines.
Using it is much like using a text-based MUD, in which the user
gives commands like say hello or go n to
communicate and move about. However, a user can still do almost everything
that can be done with one of the 3d clients (though not always
as easily).
This experimental client allows a user with only a web browser
to move about and communicate in the virtual world. The user is
presented with a page showing her or his view of the world
(rendered using Inventor 3d graphics by a program running on
my web server), with inline images set up to control movement when
clicked on. Unfortunately this client is rather slow, and its
functionality is limited by the non-interactive nature of the web.
The server program that I developed also runs under Unix, but does not make use of or require the X window system. Upon startup, the server reads in files containing shapes, persons, objects and so on from its map data directory. It also opens a file called server_log in its map directory for recording error and other messages.
When the server is running it waits for connections from clients or other servers, and controls non-player persons. Every 5 minutes the map data files are written out again in case of a power failure (or more likely, a server crash). Data files are also written out if the server process is killed or the server receives a shutdown connection request.
A connecting client, once it has found the server on which its avatar is located, recieves a list of paths, nodes, objects, persons and possibly shapes from the server. All are stored using the same data structures as the server uses, with the exception of shapes which are parsed and passed to the functions of the client's graphics library (either s3dt or Inventor).
Once a client is connected to a server, it sends requests to the server generated by user commands (like moving forward, sending a message and so on). A request is in most cases a line of text consisting of a request number followed by zero more parameters. In some cases a number of lines of text follow the request, such as an avatar description following a new avatar request. See appendix 2 for more details of the request format.
A server sends commands to its connected clients, mostly in response to requests from other clients. For example, if a client sends a request to move to a new node then the server will send commands to all its connected clients to move that user's person to a new node and its shape to a new position. Like a request, a command is in most cases a line of text containing the command number followed by a series of parameters. More details of the command format are available in appendix 3.
All the data formats are similar in structure. Their basic format is :
thing name {
attribute values
attribute values
attribute values
...
}
For example, a definition of a book object might look like :
object book {
desc "A leather bound book, with the words 'The Necronominicon' "
"enscribed on the front cover."
pos tunnel5
weight 1.5
}
This format is easily parsed by a parser generated using yacc, which
I used for all conversion from map data files to internal data structures.
It is also easily read and written by a human, which is necessary as a virtual
world designer must define his or her world using these formats. A more detailed description of the various map data files formats is available in appendix 4. Also see the section on action programming for a description of the language used in actions.
When a data file is sent to a client, the server first identifies its mime type from the file extension (for example, a file ending in .gif would have the type image/gif). The data and its type is then sent to the client, which can make use of the user's .mailcap file to determine the correct program to view the data. Alternatively, a user can configure her or his client to save or ignore incoming data rather than automatically displaying it.
The language I created uses a similar syntax to C, but without some of the difficult to implement flow control statements (such as return or break). As an example, an action associated with a door object might look like :
action door {
static dbl isopen = 1;
method open {
if (!isopen) {
isopen = 1;
chpath("tunnel1","tunnel2",0);
rotate("door",90,0,0,1);
}
}
method close {
if (isopen) {
isopen = 0;
chpath("tunnel1","tunnel2",1);
rotate("door",-90,0,0,1);
}
}
}
When an action is read in by the server, it is parsed and the code in its
methods converted to a parse tree. When a method is invoked (by
a user typing 'open door', for example), an execution function traverses the
parse to tree to interpret the code. If an error occurs at any stage of
the execution of a method, its execution immediately halts and an error
message is generated. Variables in actions may be declared outside methods (in which case they are accessible to all methods of that action), or inside a method (in which case only that method can access them). Supported variable types are :
Variables may also be specified to be local or static. Local variables are re-initialized every time a method is called, while static variables are kept between method calls. Even if a server is shut down and re-run, the values of static variables are kept.
As the example above shows, methods make changes to the world by calling built in functions. I have created 35 functions, for doing such things as moving shapes, changing the state of paths and sending messages. At the moment programmers cannot define their own functions, though this may change in the future.
Actions can be used to provide a kind of 'intelligence' for persons not controlled by a user. If an action is associated with a person, then the 'think' method of that action will be called once every 2 seconds by the server. This method can then call functions to check for players nearby, move the person about and so on.
Similarly, actions can be used to make a computer controlled person respond to messages from players. If that person's associated action has a 'listen' method, it will be called whenever the person hears a message, with the words of that message passed as parameters.
More details about actions, run-time functions and methods are available in Appendix 4.
Objects, persons, players, nodes and paths are stored by the server and clients in hash tables, to allow quick lookup by name. The server also stores shapes in this way, while the 3d clients convert the shape format received from the server to the data structures used by their 3d libraries. Both the Inventor and s3dt libraries use trees to represent the hierarchies of 3d shapes that the shape format allows.
The WWW page client was implemented as two CGI [9] programs (webcon and webinvstart) and an intermediate program (webinv) running on the web server machine, an SGI Indy. The client is started by a user filling in a web page form with his or her avatar's name and password. This invokes webinvstart, which starts webinv as a background process and then runs webcon.
The webinv process connects to a world server like a normal graphical
client program. It waits on either commands from the server, or connections
from webcon. When a connection is received, webinv reads
and acts upon a cgi request number from webcon. There are requests
for such things as movement, rotation and inventory listing. Most requests
send back to webcon HTML text, the only exception being the
image request which sends back an rgb image of the user's
current view.
webcon is run as a CGI program on the web server. When run it connects via a socket to webinv and sends a request determined by the arguments it was called with. For most arguments (like movement or rotation) the program outputs the HTML for the page the user sees, with the HTML from webinv at the bottom. This HTML includes an <img src="..."> tag, with the image source being a link to webcon. This invocation of the program connects again to webinv, sends a request for an image, then coverts the returned image to gif format and outputs it for the user to see.
This complex method of implementing a WWW page client is necessary, as CGI programs on a web server typically only run, output HTML and exit. To avoid the CGI program having to make a new connection to a virtual world server every time it is run, I use the background webinv process. The only problem with this approach is that webinv has no way of knowing if the user running the web browser has given up and moved on to visit other pages, or if he or she is simply taking a long time to do something. My solution is for webinv to exit if a user has taken no action for more than 10 minutes.
Both the 3d clients use the same graphical user interface, as shown here. This
interface was constructed using my JX user interface toolkit, which
I have been developing over the past 18 months for use in various projects.
It supports buttons, text boxes, sliders, menus, combo boxes, text lists,
scrolling windows, and other common GUI elements. The toolkit has the
advantages of being fast, suitable for programs that wish to control their own
event loops, and easily modifiable for special purposes (by me, at least). A user can rotate his or her viewpoint by moving the sliders beneath and to the right of the view window. Movement can also be controlled by the keyboard, using the arrow keys. Actions such as picking up or putting down objects, giving objects to others, doing things to objects and transferring data are invoked by buttons down the right side of the window. Messages can be sent to others by entering them in the text box at the bottom. Recieved messages from the server or other persons are displayed in the text list on the left side of the window.
The user can select an object on the ground by clicking on it in the 3d view window with the left mouse button. Clicking with the middle button picks the object up (if possible), while the right button opens a requester for doing something to that object. Clicking on a person opens a requester containing the persons name, full name and email address.
The command button on the right side of the window opens a requester for doing such things as uploading data to the server, sending data to another player and setting a new avatar. The prefs button opens requester for setting user preferences, such as what to do when data is received from the server and the 3d detail level to use.
The text client reads and executes user commands from standard input, one line
at a time. For example, a user can type go tunnel1 to move to a new
node, or view painting to invoke a method of an object's action. For
every possible command in the GUI based client, there is equivalent text
command. All error messages, messages from the server and from other players
are displayed on the user's terminal.
When a user running the text client moves to a new location, the description of that node, a list of exits and a list of persons and object nearby is displayed. The exam and about commands can be used to obtain information about objects and persons. World designers should provide text descriptions about objects and nodes (with the desc attribute) for those using this client.
The WWW page client, available at http://www.cs.monash.edu.au/courses/hons/1995/Jamie.Cameron/webinv.html, uses a graphical web browser to provide a GUI-style interface to the virtual world. Linked inline images provide buttons for a user to click on to perform various actions, such as movement or rotation. Because the web is not suited to realtime interaction, this client does not have all the features of the others. However, for those without Unix systems it is a good alternative to the text based client.
The 3d view that a user accessing the WWW client sees is rendered on the web server machine, by a program written using the Inventor toolkit. Thus users viewing the world through this client will see texture mapped shapes properly, although only at 300 x 200 resolution.
The avatar viewers read in and display shape format data.
av3d uses my s3dt toolkit for rendering, while
avinv uses the Inventor toolkit. Both viewers run
only under the X11 window system, and make use of the JX
toolkit for their user interface. I wrote these programs for users who wish to create new avatars for themselves, and wish to see what they will look like before uploading their new appearance to the server. I also found them useful when designing worlds, for previewing my shape files and shapes for objects.
I wrote this program to check the status of multiple servers,
and display their status in a window. Given a list of servers, it
pings those servers once every 30 seconds using the same method as
the simsping program. The window contains a list of server hostnames and port numbers, alongside a box displaying 'Alive' or 'Down' depending on whether the server is up or down. All the text boxes and the window were created using the JX toolkit.
In order to test the usability of my system over the Internet, I have made my client software available for download from the X consortium ftp site, at ftp.x.org. Around 200 users from various locations around the world have connected to my servers and explored. I have even managed to meet with some of them in the virtual world, and ask them what they thought of my system and about any problems they had with running the client programs or connecting to servers.
Testing by me and by other users throughout the world has shown that my system is usable, even over a wide area network. However, there is a need to improve rendering speed in the s3dt based client and to reduce the amount of data needed to be sent between server and client at connection time. I have also had requests to make available the server source code for others to create their own worlds, which I plan to do as soon as possible.
object book {
desc "A leather-bound book"
pos tunnel5
weight 1
box {
corners 0 0 0 .3 .6 .1
colour 150 100 50
pos 35 10 0
}
}
method open {
shp myShape = findshape("door");
myShape.angle = 90;
print("The door is now open");
}
Because large amounts of data need to be send between clients and servers, Internet accessible virtual worlds are currently limited to those with fast Internet connections. As ISDN and other fast network connections become available to home users, I think such systems will become more popular. There is also the need for home computers fast enough to render arbitrary 3d scenes in real time, needed for proper use of systems like mine.
[2] VRML Forum WWW page, http://vrml.wired.com/
[3] Worlds Inc. WWW page, http://www.worlds.net/
[4] Adrian Nye, The Xlib Programming Manual, O'Reilly and Associates 1992
[5] Francis E Dec, Computer God Frankenstein Controls, Kooks museum WWW page http://www.teleport.com/~dkossy/
[6] The Pet Shop Boys, Go West, From Very 1993
[7] Georg Glaeser, Fast algorithms for 3D-graphics, Springer-Verlag, 1994
[8] Open Inventor WWW page http://www.sgi.com/Technology/Inventor.html
[9] Common Gateway Interface WWW page, http://www.w3.org/pub/WWW/CGI/
Full descriptions of the various map data formats are available at :
Return to Computer Science, Monash University, Australia 3168:
http://www.cs.monash.edu.au/
10 - Glossary
11 - Appendices
11.1 - Source code
As the source code for this project is approximately 30,000 lines, I have
not included it with this report. For those within the Department of Computer
Science, source is available in the following directories :
Client and server source code.
JX toolkit source code.
s3dt library source code.
Map data files for virtual worlds. 11.2 - Client-server request protocol
A client request is a string of characters terminated by a newline. The request
is broken into words, each word being a string of characters separated by
whitespace. Words containing whitespace are allowed, if surrounded by quotes.
The first word of a request is the request number (defined in sim.h in
the source code), and the following words the parameters to the request. Valid
requests and their parameters are :
Move along path number link from current position.
Send the words to nearby persons.
Send the words to all persons on this server.
Invoke the method of an action, with the given
parameters.
Drop the object from this player's inventory.
Rotate to the given angle (in degrees).
Transfer the object from this player's inventory to another
person.
Transfer size bytes of data to the server using the given
port, to be stored as dataname.
Request transfer of data stored on the server as dataname to
player.
Request a list of methods for an action.
Request list of data files associated with this player.
Delete data stored on server as dataname.
Totally destroy this player.
Set a new avatar for this player. This request must be followed by shape
format data.
Set a new password for this player, which must be provided at all
successive connections to a server.
Set this player's email address.
Set this player's full name.
11.3 - Server-client command protocol
Like client requests, server commands consists of a single line containing
a command number followed by parameters. Valid commands are :
Move this player to the given node.
Display the message words to the user.
Display an error message, determined by number.
Create a new object with the given name. This command must be followed by
the object format data of the object to add.
Create a new person with the given name. This command must be followed by
person format data.
Create a new shape with the given name. This server command must be
followed by shape format data.
Move the named object to a new node.
Move the named person to a new node.
Add the given x, y and z values to the position of the
named shape.
Delete the named object.
Delete the named person.
Delete the named shape.
Re-connect this client to a new server, on the given host and port.
Placed the named object in the named person's inventory.
Remove the object from the person's inventory and place it at their
location.
Set the rotation of the named shape to the given angle and axis.
Transfer the named object from one person to another.
Connect to the server at the given port and transfer size
bytes of data.
This command is followed by lines lines of text, to be displayed
to the user.
Send in response to a req_actlist request, to give the allowable
methods for an object.
Change the colour of the named shape to the give red/green/blue triple.
Change the surface of the named shape to the given type.
Send in response to a req_ls request, to list the data files
associated with this player.
Change the state (open or closed) of the path between the two given nodes.
Disconnect from the server.
Set the email address of the given person.
Set the full name of the given person.
Teleport the player to the given node.
11.4 - Map data file formats
My guide to setting up a server, which details the uses and layouts of the
various map files is available at
http://www.cs.monash.edu.au/courses/hons/1995/Jamie.Cameron/serverguide.html.
Jamie Cameron / 1995