| TWiki . Javadesktop . ProjectWonderlandArchitecture |
ManagedObjects) and
provides APIs for the synchronized update of the state of these objects in
response to events from multiple clients. Updates to ManagedObjects are
themselves transactional -- either a coherent set of state updates happen
across a set of objects or they do not happen at all. All items within a
game or virtual world are represented by ManagedObjects on the server, for
example, rooms, players, tools, weapons, or any other virtualized real-
world object that exists in the world. Details on Project Darkstar can
be found at http://www.projectdarkstar.com.
The client is a desktop Java application and is based upon two technologies
to render the 3D world: Java 3D and Looking Glass 3D (LG3D). Java 3D, a standard
extension to Java SE, renders sets of 3D objects to the screen, making
use of hardware acceleration if possible. Details on Java 3D can be found
at https://java3d.dev.java.net/. Project Looking Glass provides a 3D
desktop environment. It provides a 3D Windowing environment and a set of
API to build 3D applications. Details on Project Looking Glass
can be found at https://lg3d-core.dev.java.net/.
main() method). The org.jdesktop.lg3d.wonderland.darkstar.server.WonderlandBoot class serves this purpose
by implementing the Darkstar AppListener interface. The implementation of its initialize() method performs some very basic tasks
which kick-starts the creation of the Wonderland world. They are:
org.jdesktop.lg3d.wonderland.darkstar.server.UserManager class which maintains the list of users (i.e. clients) which connect to the server.
org.jdesktop.lg3d.wonderland.darkstar.server.cell.MasterCellCacheGLO class which maintains the list of classes which maintains the cache of cells visible to a user. (Not really sure what this means Bernard.)
org.jdesktop.lg3d.wonderland.darkstar.server.ChecksumManagerGLO class which manages a series of checksums for classes representing assets in the world.
ChannelInfo.USER_CHANGE which communicates changes in the client's status.
WonderlandBoot.loggedIn() method is invoked, which simply creates a new
instance of the org.jdesktop.lg3d.wonderland.darkstar.server.WonderlandSessionListener class. It is this class which
handles future changes in the state of the client, and in particular
creates the avatar when a user logs in (see WonderlandSessionListener.processAvatarSetupMessage()).
org.jdesktop.lg3d.wonderland.darkstar.server.cell.CellGLO class. (The
suffix "GLO" is a hold-over from an earlier version of Project Darkstar
where managed objects were called "Game Logic Objects" (or GLOs)).
There are two types of cells in Wonderland: stationary cells and moveable
cells. Stationary cells represent regions which do not move, while moveable
cells represent graphics which do move. Avatars are the best (and perhaps
only) example of a moveable cell. All stationary cell classes extend
org.jdesktop.lg3d.wonderland.darkstar.server.cell.StationaryCellGLO and all moveable cell classes extend org.jdesktop.lg3d.wonderland.darkstar.server.cell.MoveableCellGLO.
Various classes are used to define stationary cells within the Wonderland architecture.
The most basic is the "world root" cell (see org.jdesktop.lg3d.wonderland.darkstar.server.cell.WorldRootCellGLO class) which
is the root of all cells in the world and is also responsible for creating the
world. At present time, the WorldRootCellGLO creates its structure of cells using
hard-coded lines of code. (See for example, WorldRootCellGLO.buildFullWorld().) In the future, a more flexible architecture to
build worlds is planned.
Currently, the following stationary classes exist to represent the following (in package org.jdesktop.lg3d.wonderland.darkstar.server.cell):
simple terrain (SimpleTerrainCellGLO), slide show (SlideShowCellGLO),
model viewer (ModelViewerCellGLO), animated (AnimatedCellGLO), audio (AudioCellGLO), and shared application (SharedApp2DCellGLO). The only moveable
cell that is exists is the avatar cell (AvatarCellGLO).
CellGLO class which provides most of the services
necessary for cells. Each cell has a unique ID, generated by a central
facility (see org.jdesktop.lg3d.wonderland.darkstar.server.CellIDGenerator) and also a unique name formed as "CELL_"
plus ID. (see CellGLO.getCellID() and CellGLO.getGLOName() methods). A cell's
ID is simply a number encapsulated by an instance of the org.jdesktop.lg3d.wonderland.darkstar.common.CellID class.
CellGLO.getOrigin() method
returns the origin as the cell in the form of an instance of class Matrix4d.
A cell also has a bounds, represented by the Java 3D Bounds class which
describes its physical extent. The subclasses of CellGLO manage the cell's
bounds by overriding the CellGLO.getBounds() method.
CellGLO.addParentCell() and
CellGLO.removeParentCell() methods, respectively. The CellGLO.getParentCellIDs() method
returns an array of instances of class CellID, each of which identifies a parent cell. The
methods CellGLO.addChildCell() and CellGLO.removeChildCell() add and remove
children to and from the cell, respectively. The CellGLO.getChildren() returns
a collection of children of the cell.
At any time, some of a cell's children may be invisible, which is conditional
upon some visible bounds. The CellGLO.getVisibleCells() method returns a
collection of children cells that are visible given a certain bounds. Typically
the visible bounds depends upon the viewing frustum of the avatar.
CellGLO.openCellChannel() method.
The CellGLO.getCellChannel() method returns the cell's channel. Clients are added as
listeners to the channel via the CellGLO.addUserToCellChannel() method and removed
via the CellGLO.removeUserFromCellChannel() method. Each of these two methods
takes the unique id of the client session as argument. See Section 6 below
regarding details of the client-server communication architecture in Project
Wonderland.
CellGLO class on the server has a corresponding Cell class on the client
which is responsible for rendering the cell. The name of the corresponding
client cell class is defined by each of the individual server-side cell subclasses via
the CellGLO.getClientCellClassName() method.
A server-side CellGLO communicates its visual contents and other setup data
via an instance of a class that implements the org.jdesktop.lg3d.wonderland.darkstar.common.CellSetup interface.
This is returned from the CellGLO.getSetupData() method that
is implemented by each of the individual server-side CellGLO subclasses.
The CellSetup interface itself is simply an empty interface which extends the
java.io.Serializable interface so that it may be sent across the wire. Each server-side
CellGLO class defines its own "setup" class that implements the CellSetup interface. Examples (in package org.jdesktop.lg3d.wonderland.darkstar.common)
include AnimatedCellSetup, AvatarCellSetup, ModelViewerCellSetup,
SharedApp2DCellSetup, SimpleCellSetup, and SlideShowCellSetup. The
SimpleCellSetup class is used, for example, by the simple terrain cell and
has methods which return the name of disk files storing the scene.
Cells which should be currently kept in memory by the client is
managed by the server via an instance of org.jdesktop.lg3d.wonderland.darkstar.server.cell.UserCellCacheGLO class, an instance of this
class exists for each user (which is equivalent to saying "client") and
is created when the user logs in. All instances of UserCellCacheGLO are managed
by the instance of MasterCellCacheGLO class that was created by WonderlandBoot (see section 4.1). They are managed objects within the Project
Darkstar infrastructure.
The server-side cell caches support several state changes to CellGLOs They are:
cell created, root cell created, cell moved, cell deleted, and add parent to cell.
At the present time, the UserCellCacheGLO.revalidate() method considers those
CellGLOs which are currently visible and adds those CellGLOs which are new and deletes
from the client's memory those which are no longer visible. Changes in the
state of CellGLOs are communicated via a dedicated channel (named CELL_CACHE) associated with the instance of
UserCellCacheGLO class. At present, the messages that are communicated on this channel are
serialized instances of the org.jdesktop.lg3d.wonderland.darkstar.common.messages.CellHierarchyMessage class.
The visible cells are determined by the position of the avatar.
Its visible domain is determined by an instance of class org.jdesktop.lg3d.wonderland.darkstar.common.AvatarBoundsManager via its
getProximityBounds() method. This method defines the visible area as a sphere of
a specified radius (AvatarBoundsManager.PROXIMITY_SIZE = 200.0) from the center
of the avatar.
org.jdesktop.lg3d.wonderland.Main class, as its name implies, implements the static main() method to
start-up the client. It initializes its user interface and reads in any
mutable configuration options from an external XML-formatted configuration
file.
The initialization of the connection with the server happens via it inner class named
StartupListener, which implements the Lg3dStartupListener interface, from
Project Looking Glass -- this listener's startupComplete() method is invoked
when the initialization of the graphics is complete. In turn, the implementation
of the startupComplete() method displays a login dialog (see class org.jdesktop.lg3d.wonderland.LoginDialog)
which accepts login information from the user. It initiates a connection to
the Wonderland server and invokes the method Main.enableMainWindow() to "turn on" the
Wonderland client.
All communication with the Darkstar-based Wonderland server is managed by an instance of class
org.jdesktop.lg3d.wonderland.darkstar.client.ChannelController. (This seems to be somewhat misleadingly named as it doesn't
control channels, instead it provides a direct client-server communication mechanism.) A new connection to the server is initiated via the
ChannelController.initCommunications() method. See Section 6 below for details
of class ChannelController.
org.jdesktop.lg3d.wonderland.scenemanager.WonderlandUniverseFactory, creates the main
drawing canvas and initializes some basic viewing parameters. This instance is
created by an instance of class org.jdesktop.lg3d.wonderland.scenemanager.WonderlandPlatformConfig, which in turn, is specified by
the lg.platformConfigClass property.
org.jdesktop.lg3d.wonderland.scenemanager.WonderlandSceneManager extends
the LG3D SceneManagerBase class, an abstract class which implements the LG3D
SceneManager interface. The LG3D SceneManagerBase class handles communication with
the LG3D display server (the moral equivalent of the X Windows Server) via its
implementation of the LG3D interface DisplayServerManagerInterface.
The WonderlandSceneManager.initialize() method contains the bulk of the functionality
of this class. It creates an instance of class org.jdesktop.lg3d.wonderland.scenemanager.WorldController with an instance of the
Java 3D BranchGroup class to which the WorldController will attach all of the
visual content. It also adds the instance of the Java 3D BranchGroup class as a child
of the LG3D display server's root.
The instance of WonderlandSceneManager also creates an instance of an LG3D StandardAppContainer
class, using a null-style layout manager. The implementation of the
SceneManager.addFrame3D() and SceneManager.removeFrame3D() methods add and remove frames to
and from the instance of class StandardAppContainer. The usage of this is currently unclear.
The instance of class WonderlandSceneManger is installed according to the LG3D specification as
follows: the createSceneManager() method of org.jdesktop.lg3d.wonderland.scenemanager.WonderlandConfigControl returns an instance of
class WonderlandSceneManager. The Main class sets the "lg.configclass" property
to "org.jdesktop.lg3d.wonderland.scenemanager.WonderlandConfigControl". (Additional
configuration information for the scene manager is also handled by the
WonderlandConfigControl class, which reads an XML-formatted file of configuration
options, by default: "/org/jdesktop/lg3d/wonderland/scenemanager/resources/wonderland.lgcfg".)
WorldController handles all of the visible content in the Wonderland world.
As class members, it maintains instances of two important client-side classes:
org.jdesktop.lg3d.wonderland.scenemanager.UserCellCache and ChannelController. The WorldController takes as an argument a Java 3D
BranchGroup to which it adds lighting: an ambient light of color RGB = {0.7, 0.7, 0.7},
and two directional lights. One directional light is white and is down-to-the-left. The
second directional light is RGB = {0.2, 0.2, 0.3} and is up-to-the-left. (TODO: What's
the effect of this lighting descriptively?)
Details of classes UserCellCache (section 5.4) and ChannelController (section 5.x) are found below.
UserCellCache. The loading/unloading
of cells and changing their state is controlled entirely by the server through messages
send from the server to the client, formatted as instances of class CellHierarchyMessage.
The UserCellCache.handleMessage() method handles these server events, sent over
a communication channel maintained by the Project Darkstar infrastructure and handled
by an instance of class org.jdesktop.lg3d.wonderland.darkstar.client.UserCellCacheChannelListener.
A common operation, particular at client boot-time, is the request to create new cells on the client
side via a message of type CellHierarchyMessage.LOAD_CELL. Using the configuration
information embedded in the CellHiearchyMessage, an instance of the client-side cell
class is create and initialized. The new cell is added to the HashMap cache of cells,
and the thread (an instance of inner class CellUpdateThread within class UserCellCache) is signalled to update the set of visible
cells to render (the UserCellCache.visibleCells member variable).
The instance of class UserCellCache also manages the list of cells in which the avatar is currently positioned
via the UserCellCache.avatarInCells member variable (a HashSet). This set is updated when the
CellUpdateThread is signalled that an update has occurred. Cell enter and exit
events are generated--as represented by classes CellEnterEvent and CellExitEvent (in package org.jdesktop.lg3d.wonderland.scenemanager.events),
respectively--and posted.
Class UserCellCache currently only implements a subset of the cell states: VISIBLE
and INACTIVE. The following cell states are currently not handled: ACTIVE, DISK, and
BOUNDS.
Class UserCellCache also implements the org.jdesktop.lg3d.wonderland.scenemanager.UserMotionListener interface which receives
notification when the avatar moves (via the userMoved() method). The implementation of
the UserCellCache.userMoved() method is currently basic: it simply updates the status
of the visible cells and generates cell enter/exit messages using the updated position
of the avatar.
UserGLO -- basic user information, like name and preferred color
AvatarCellGLO -- the cell where the user's avatar is rendered
UserCellCacheGLO -- the cells that are visible to a specific user
UserCellCacheGLO to see if that client has already loaded all the cells in its immediate area.
If the server finds a cell the client hasn't seen yet, it sends it a message, telling the client to load the new cell.
WonderlandBoot.loggedIn()).
org.jdesktop.lg3d.wonderland.darkstar.common.messages.ErrorMessage (ditto, and also in WonderlandSessionListener.processFileTransferMessage().
org.jdesktop.lg3d.wonderland.darkstar.common.messages.NativeApplicationMessage as messages in reply to a "create application cell" message (in WonderlandSessionListener.processNativeApplicationMessage()).
org.jdesktop.lg3d.wonderland.darkstar.common.messages.SoftphoneMessage (in the callStatusChanged() and processSoftphoneMessage() methods of WonderlandSessionListener.
ChannelController.handleMessage().
NativeApplicationMessage messages are handled by the receivedMessage() method of the inner class MessageListener of class org.jdesktop.lg3d.wonderland.appshare.ServerApp2DCell.
SoftphoneMessage messages are also handled by ChannelController.handleMessage().
NativeApplicationMessage. These are sent by the constructor of class ServerApp2DCell.and the sendMessage() method of ChannelController.
org.jdesktop.lg3d.wonderland.darkstar.common.messages.SoftphoneMessage. These are sent by the connectSoftphone() and disconnectSoftphone() methods of ChannelController.
org.jdesktop.lg3d.wonderland.darkstar.common.messages.AvatarSetupMessage initiated by the method loggedIn() in class ChannelController.
org.jdesktop.lg3d.wonderland.darkstar.common.messages.CellMessage. Currently there appear to be none.
NativeApplicationMessage. These are handled by the receivedMessage() method of org.jdesktop.lg3d.wonderland.darkstar.server.WonderlandBaseSessionListener, and subsequently by its processNativeApplicationMessage() method.
SoftphoneMessage. These are handled by the receivedMessage() method of WonderlandSessionListener.
org.jdesktop.lg3d.wonderland.darkstar.common.messages.AvatarSetupMessage messages . These are also handled by the receivedMessage() method of WonderlandSessionListener.
org.jdesktop.lg3d.wonderland.darkstar.common.messages.CellMessage messages, dispatched to instances of class org.jdesktop.lg3d.wonderland.darkstar.server.CellMessageListener.
USER_CHANGE, CELL_CACHE, AVATAR_P2P, AVATAR_CELL, and
SERVER_MANAGER_CHANNEL. A channel provides a communications mechanism between clients and also between a client and its server.
USER_CHANGE communication channel is created by WonderlandBoot in its initialize() method, and all new clients
are automatically added to it. It is used exclusively for server-->client communication.
The server transmits the following messages to the client over this channel:
org.jdesktop.lg3d.wonderland.darkstar.common.messages.UserChangedMessage when users are added (USER_ADD, in method processAvatarSetupMessage() of class WonderlandSessionListener) or when users leave (USER_LEFT, in method disconnected() of class WonderlandSessionListener).
receivedMessage() method of class org.jdesktop.lg3d.wonderland.darkstar.client.UserChannelListener.
CELL_CACHE channel for each client connected. The name of the
channel takes the form: user + CELL_CACHE, where 'user' is the name of the user. The CELL_CACHE
channel for a client is created by the instance of class UserCellCacheGLO that corresponds to that client (in its contructor). Each new client is automatically
added to one of these channels.
Each instance of class UserCellCacheGLO has a CELL_CACHE channel. Only one client/user (the user who's cache it is) is subscribed to that CELL_CACHE channel. The subscription is managed in the login() method of class UserCellCacheGLO. This channel is used exclusively for server-->client communication.
The server transmits the following messages to the client over this channel. The messages are sent by the instance of UserCellCacheGLO.
CellHiearchyMessage messages, which can be of the kind: LOAD_CELL, MOVE_CELL, CELL_INACTIVE, ADD_PARENT, REMOVE_PARENT, SET_WORLD_ROOT, and DELETE_CELL.
receivedMessage() method an instance of class org.jdesktop.lg3d.wonderland.darkstar.client.UserCellCacheChannelListener.
AVATAR_P2P channel for each client connected. The name of the
channel takes the form: user + AVATAR_P2P, where 'user' is the name of the user.
This channel is created by an instance of class AvatarCellGLO during its constructor, and then maintained by that instance of AvatarCellGLO. Another client may request to join an client's P2P? channel via the AvatarCellMessage(JOIN_P2P) message sent on
the AVATAR_CELL channel (see below).
Each avatar sends its motion updates over its client's AVATAR_P2P channel, so any client that cares about those updates (generally any other client in visual range of the avatar) will subscribe to it.
The server transmits the following messages to a client over this channel:
org.jdesktop.lg3d.wonderland.darkstar.common.messages.AvatarP2PMessage, of which there are two kinds: SETUP message is sent by the receivedMessage() method of class AvatarCellGLO in response to an AvatarCellMessage(JOIN_P2P) message.
SPEAKING message is sent by the callStatusChanged() and processAvatarCellMessage() methods of class WonderlandSessionListener and the setSpeakingStatus() method of AvatarCellGLO.
receivedMessage() of an instance of class org.jdesktop.lg3d.wonderland.darkstar.client.AvatarP2PChannelListener.
A client transmits instances of class AvatarP2PMessage over this channel, though only of kind MOVE and CHAT: MOVE message is sent by the userMoved() method of class org.jdesktop.lg3d.wonderland.scenemanager.avatar.Avatar, in response to user interaction.
CHAT message is sent by the sendChatMessage() method of class Avatar.
handleMessage() method of an instance of class org.jdesktop.lg3d.wonderland.darkstar.serverAvatarP2PChannelListenerGLO . (The method is only used for logging purposes.)
Thus, this channel is used for inter-client communication (for AvatarP2PMessages of kind MOVE and CHAT), and for server-->client communication (for AvatarP2PMessages of kind SETUP and SPEAKING).
AVATAR_CELL channel is created by an instance of class AvatarCellGLO during its constructor. The name of the
channel takes the form: user + AVATAR_CELL, where 'user' is the name of the user.
The server transmits the following messages to the client over this channel:
AvatarCellMessage, which has one basic kind: SETUP. This is sent when a an avatar's cell (i.e. AvatarCellGLO) first becomes visible.
CellGLOs and
adds the client to the =CellGLO='s channel if it (the channel) exists. Currently, only the avatar
CellGLO? creates a channel for itself. At that point, a SETUP message is sent to
the client, which keeps a reference to the channel for future communication.
The server receives the following messages from the client over this channel:
AvatarCellMessage. It handles these messages via method receivedMessage() in an instance of class AvatarCellGLO (for messages that are of kind CELL_MOVE, CELL_ENTER, and CELL_EXIT) and also via the receivedMessage() method of an instance of WonderlandSessionListener (for messages that are of kind AVATAR_MOVE, AVATAR_MUTE and JOIN_P2P.
AvatarCellMessage over this channel (see class org.jdesktop.lg3d.wonderland.darkstar.client.cell.AvatarCell.)
The client receives messages over this channel. It handles them via the receivedMessage() method of an instance of class org.jdesktop.lg3d.wonderland.darkstar.client.cell.AvatarCellChannelListener.
SERVER_MANAGER_CHANNEL communication channel, created by an instance of class org.jdesktop.lg3d.wonderland.darkstar.server.ServerManagerGLO,
is used to communication server management information to the client. Currently, the server itself and a special client (hardcoded to name "ServerManager") are
added to this channel.
The server transmits and receives instances of class org.jdesktop.lg3d.wonderland.darkstar.common.messages.ServerManagerMessage to the client over this channel, of which there are four kinds: STATUS, FULL_STATUS, CHANGE_UPDATE_INTERVAL, and SET_USER_LIMIT.
The only client to the SERVER_MANAGER_CHANNEL communication channel is provided by an instance of class org.jdesktop.lg3d.wonderland.management.ManagerUI which can be opened using the ANT run-manager target.
Cell. An example would be when a user's cursor hovers over a widget (see, for example, the sample module)
CellGLO on the server. An example would be when a user clicks on a widget (see the sample module for an example)
Cell on client C2 causes local state change in Cell (no change in server state)
Cell updates appearance
Cell broadcasts message to other clients on Cell's channel; message identifies "kind of change" and new state of Cell
Cell updates its appearance
Cell on client C2 causes state change in CellGLO on server
Cell updates local state (if necessary) and appearance
Cell
CellGLO
CellGLO updates its state
Cell's channel to all clients except originating client. Message describes "kind of change" and new state.
Cell (if necessary) and appearance.
The above flow of control differs from conventional Model-View-Controller (MVC) in the following features:
CellGLO determines its Cell (which is equivalent to saying that the model determines its view). This means that it is not possible to use the same CellGLO class to be rendered by multiple Cell classes. For example, a CellGLO class representing a die could not have two Cell classes that provided different renderings of a die.
Cell is often provided by an inner class of the Cell class.
Cell, it's necessary to synchronise between the clients. This requirement is outside MVC, and is handled in Wonderland by the use of messages to the channel owned by a Cell.
Cell on client C2 causes state change in CellGLO on server
CellGLO
CellGLO
CellGLO updates its state
Cell's channel to all clients. Message describes "kind of change".
CellGLO
Cell (if necessary) and appearance.
The reason for this difference is performance. It is important that the user is notified of a change of appearance as soon as possible (i.e. before notifying the server).
Main class creates the main window and adds an instance of the LG3D Lg3dConnector class to the main window. This, in turn, starts the LG3D display server. Upon initialization, the L3GD display server initializes the universe, windowing system, view, creates the root scene graph, and initializes the scene manager.
WorldController, which creates a new instances of the ChannelController and UserCellCache classes.
StartupListener.startupComplete() method is called which raises the Wonderland Login dialog.
WonderlandClientListener.loggedIn().
AvatarSetupMessage message to the Darkstar server via its client-server communication mechanism with information about the avatar, such as its visual model.
WonderlandBoot.initialize() method creates new instances of classes ServerManagerGLO, UserManager, MasterCellCacheGLO, and ChecksumManagerGLO. A publish/subscribe channel is also created named USER_CHANGE.
MasterCellCacheGLO instance creates a new instance of class WorldRootCellGLO. In turn this calls the WorldRootCellGLO.buildWorld() method which creates all of the cells in the world.
WonderlandSessionListener receives an AvatarSetupMessage message from the client. It creates a new instance of class UserGLO.
UserGLO instance creates a new AvatarCellGLO instance, which in turn creates a new UserCellCacheGLO instance.
UserCellCacheGLO instance creates a publish/subscribe channel named user+CELL_CACHE, where 'user' is the name of the user.
AvatarCelLGLO instance then opens a publish/subscribe channel named AVATAR_P2P and a channel named user+AVATAR_TILE, where 'user' is the name of the user.
WonderlandSessionListener instance then joins the client to the USER_CHANGE channel and sends a UserChangedMessage(USER_ADDED) message to the client. It then calls the login() method on the UserGLO instance.
UserGLO.login() method adds a reference of the user to the hash map relating user ID's to user object references. It calls AvatarCellGLO.login().
AvatarCellGLO.login() adds the receiving instance of AvatarCellGLO to the MasterCellCacheGLO instance. It then calls UserCellCacheGLO.login() which joins the client to the user+CELL_CACHE channel, adds itself (the UserCellCacheGLO) to the MasterCellCacheGLO instance, and sends a CellHierarchyMessage(LOAD_CELL) message to the channel named "user+CELL_CACHE", and then sends a CellHiearchyMessage(SET_WORLD_ROOT) message to the channel named "user+CELL_CACHE".
UserGLO.login() method then calls the UserCellCacheGLO.avatarCellMoved() method, which computes the list of visible cells and sends CellHierarchyMessage(LOAD_CELL) messages for all visible cells on the channel named "user+CELL_CACHE". It also sends CellHierarchyMessage(DELETE_CELL or CELL_INACTIVE) messages for all newly non- visible cells on the channel named "user+CELL_CACHE".
WonderlandSessionListener finally sends UserChangedMessage messages to each of the clients via the USER_CHANGE channel to notify them of the new client.
keyPressed() method of class org.jdesktop.lg3d.wonderland.scenemanager.WalkBehavior. The state of the instance of the inner class Stimulus is updated to reflect the key state change.
scheduleUpdate() of the instance of class org.jdesktop.lg3d.wonderland.scenemanager.AvatarControlBehavior is called which tells it that pending updates to the avatar state exists.
AvatarControlBehavior.processStimulus() method wakes up and calls the WalkBehavior.updateState() method which updates the position state of the avatar.
UserMotionListener are notified of the new position of the avatar via the method userMoved(). One example of an implementation of UserMotionListener is class UserCellCache, whose userMoved() method calls the UserCellCache.updateCells() method. (Another example implementation of the interface is class AvatarCell).
updateCells() method computes the visible cells based upon the user's viewing frustum. It updates the state of each cell and the list of visible cells. For all visible cells, it updates the list of cells the avatar is currently standing in. It causes events of type CellEnterEvent and CellExitEvent to be sent to the appropriate cells (within the LG3D event framework). (At this time the AvatarCellMessage types CELL_ENTER and CELL_EXIT are not sent to the server, nor does the server take any action upon receiving these events).
AvatarCell.userMoved() method sends an AvatarCellMessage(AVATAR_MOVE & CELLMOVE) to the server via the AVATAR_TILE channel. The position of the avatar is updated on the server and the UserCellCacheGLO is asked to revalidate itself (which computes the list of visible and invisible cells, updates its state, and informs the client of such).
----- Revision r14 - 07 May 2008 - 03:14:12 - Main.jslott
|