The Source for Java Technology Collaboration


Home | Changes | Index | Search | Go

ProyectoWonderlandArquitectura

Article:Proyecto Wonderland. Arquitectura del Software (v0.3, v0.4)

autor: Jordan Slott (jslott@dev.java.net)
traductor: Miguel Alonso González (miguel@nicer.es)

1. Introducción

El proyecto Wonderland es una plataforma de software para la creación de mundos virtuales 3D, en un principio aporta a participantes distribuidos geográficamente colaborar entre sí. Este documento describe la arquitectura del software del proyecto Wonderland. Este documento esta dirigido a desarrolladores que deseen ampliar y modificar el proyecto Wonderland. El proyecto Wonderland está en un estado primigenio lo que implica que la arquitectura del software así como este documento pueden cambiar sustancialmente.

2. Componentes principales. Arquitectura Cliente-Servidor

El proyecto Wonderland está basado en Java y en el modelo cliente Servidor. El software del servidor esta basado en el proyecto Darkstar, una tecnología para Java SE que da soporte a “juegos” multijugador. (La palabra juego se pone entre comillas porque aunque el proyecto Darkstar esta dirigido hacía el mundo de los juegos y él ha sido empleado en otros contextos). El proyecto Wonderland gestiona una colección de objetos (llamados ManagedObjects) y tiene un API para sincronizar la actualización del estado de estos objetos en respuesta a eventos desde múltiples clientes. Las actualizaciones a los ManagedObjects son transaccionales (el cambio de estado de los objetos debido a las actualizaciones puede suceder a través de una serie de objetos o pueden no ocurrir nunca. Todos los objetos dentro de un mundo virtual están representados por ManagedObjects en el servidor, por ejemplo, las habitaciones, los jugadores, las herramientas, armas, o cualquier otro objeto). Más información sobre Proyecto Darkstar puede ser encontrada en: http://www.projectdarkstar.com.

El cliente es una aplicación Java de escritorio (J2SE) y está basada en dos tecnologías de renderizado 3D: Java 3D y Looking Glass 3D (lg3d). Java 3D, es una extensión estándar de Java SE, renderiza un conjunto de objetos 3D en tiempo real, si es posible usa aceleración de hardware. Más información sobre el proyecto java 3D: https://java3d.dev.java.net/.

El proyecto lg3d (Looking Glass) es un escritorio 3D y tiene un conjunto de API's para desarrollar aplicaciones 3D. Más información sobre este proyecto se puede encontrar en: https://lg3d-core.dev.java.net/.

3. El Mundo Virtual 3D

Un mundo virtual esta compuesto de una colección de “celdas”, cada una de las cuales representa un volumen 3D en el mundo. Un mundo tiene un sistema de coordenadas cartesianas (en adelante coordenadas del mundo) simple. Desde la perspectiva del observador, el eje de las X positivas es hacía la dch, el positivo de las Y hacía arriba y el eje Z es hacía el usuario, este sistema de coordenadas es el mismo definido por Java 3D. Las celdas pueden ser escenarios o objetos en el mundo virtual. Las personas, llamadas Avatares son también representadas por celdas.

Cada celda tiene una posición y unos límites (entorno que ocupa que define un volumen) dentro del mundo virtual. El origen de una celda esta dada en coordenadas del mundo que corresponden al centro de la celda. Una celda también tiene “coordenadas de celda”, donde el centro de la celda es (0,0,0).

Una celda puede contener cero o más celdas, y por tanto surge la noción de parentesco, “padre” e “hijos” por cada celda -una simple celda “master”, representa el mundo entero y contiene todas las otras celdas. Una celda puede tener multiples “parientes”, si el amplia el limite físico de mas de una celda pariente. Sin embargo, las celdas pueden solaparse con una celda y no se necesita estar contenida en su totalidad en una celda. (Esto suena como que los límites de una celda pueden solaparse con los límites de otra celda).

4. Arquitectura del Servidor

4.1 Clase Darkstar Boot y Data Management

El proyecto Darkstar requiere una clase bootstrapping para inicializar el “juego”, (lo cual remplaza al metodo main()). La clase: org.jdesktop.lg3d.wonderland.darkstar.server.WonderlandBoot

Tiene este próposito por implementar el interface Darkstar AppListener. La implementación de su metodo initialize() realiza alguna tareas básicas las cuales inician la creación del mundo Wonderland. Estás son:

  1. Crear una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.server.UserManager la cual gestiona la lista de usuarios que conectan al servidor.
  2. Crear una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.server.cell.MasterCellCacheGLO la cual mantiene la lista de clases que manejan la cache de celdas visibles al usuario.
  3. Crear una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.server.ChecksumManagerGLO la cual gestiona una serie de “checksums” para las clases que representan activos en el mundo.
  4. Abrir un canal de comunicación llamado ChannelInfo.USER_CHANGE el cual comunica cambios de estado de los clientes.

Cuando un nuevo cliente abre una conexión en el servidor Wonderland, el método WonderlandBoot.loggedIn() es invocado, el cual simplemente crea una nueva instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.server.WonderlandSessionListener. Esta es la clase que maneja futuros cambios en el estado del cliente, y en particular crea el Avatar con el usuario autenticado (vease WonderlandSessionListener.processAvatarSetupMessage()).

4.2 Arquitectura de la Celda

El proyecto Wonderland emplea el proyecto Darkstar que es una plataforma de juego en la capa servidor, donde cada celda es representada por un “managed object”. La clase abstracta base para todas las celdas o “managed object” es la clase org.jdesktop.lg3d.wonderland.darkstar.server.cell.CellGLO (El sufijo “GLO” es de una anterior versión del Darkstart donde los “managed objets” eran llamados “Game Logic Objects” o GLOs).

Hay dos tipos de celdas en Wonderland: celdas estáticas y celdas dinámicas. Las celdas estáticas representan regiones que no se mueven, mientras las dinámicas representan gráficos que se pueden mover. Los Avatares son el mejor ejemplo ( y tal vez el único) de celdas dinámicas. Todas las clases de celdas estáticas heredan (“extend”) de la clase: org.jdesktop.lg3d.wonderland.darkstar.server.cell.StationaryCellGLO y todas las dinámicas de la clase: org.jdesktop.lg3d.wonderland.darkstar.server.cell.MoveableCellGLO

Varias clases se usan para definir celdas estáticas en la Arquitectura del Wonderland. La más básica es la celda “world root”, es la clase org.jdesktop.lg3d.wonderland.darkstar.server.cell.WorldRootCellGLO la cual es la raíz de todas las celdas del mundo y es responsable de la creación del mundo. Actualmente, la WorldRootCellGLO crea su estructura de celdas mediante líneas de código. Véase por ejemplo, WorldRootCellGLO.buildFullWorld(). En el futuro, se planea tener una arquitectura más flexible para la creación de mundos.

Actualmente, las siguientes clases estáticas existen para representar lo siguiente: en el paquete org.jdesktop.lg3d.wonderland.darkstar.server.cell: terrenos simples (SimpleTerrainCellGLO), presentación de diapositivas (SlideShowCellGLO), visores del modelo (ModelViewerCellGLO), animación (AnimatedCellGLO), audio (AudioCellGLO), y compartir aplicaciones (SharedApp2DCellGLO).

La única celda dinámica que existe es la celda Avatar (AvatarCellGLO).

  • La celda “simple terrain” se utiliza para definir entornos básicos en el mundo, toma el nombre de un fichero externo el cual define la geometría de los entorno.
  • La celda “slideShow” se usa para definir una serie de imágenes (presentación de diapositivas), que se mostrarán en una secuencia, toma el nombre de un fichero como patrón y puede utilizar caracteres comodín (“%”) o una numeración para ir mostrando las imágenes. Las secuencias de imágenes puedes ser manejadas por el usuario.
  • La celda “model viewer”, necesita un estudio más a fondo.
  • La celda “animated” representa una serie de imágenes las cuales son animadas en el mundo, utiliza un “array” de nombres de ficheros que componen la animación.
  • La celda “audio”, es una extensión de la celda “animated”, representa la reproducción de audio emitido desde un cierto origen en el mundo.
  • La celda “shared application” representa una aplicación X -Windows que está siendo mostrada en el mundo y que puede ser interactuada por los avatares.

4.3 Características de una Celda

Todas las clases celda heredan de la clase CellGLO que proporciona la mayoría de los servicios que necesitan las celdas. Cada celda tiene un único “id”, generado por una utilidad central (véase org.jdesktop.lg3d.wonderland.darkstar.server.CellIDGenerator) y también un único nombre formado por “CELL_” más ID. (véase los métodos CellGLO.getCellID() y CellGLO.getGLOName()). El ID de una celda es simplemente un número encapsulado por una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.common.CellID

4.3.1 Origen de celda y límites

El mundo tiene definido cada posición de las celdas por su origen, está especificado por una matriz de 4x4 (véase la clase Matrix4d de java 3d; la clase Matrix4d se usa en java 3d para definir transformaciones generales, tales como rotaciones, escalados y translaciones. No parece importar que el origen de las celdas pueda ser una combinación de estas transformaciones, sin embargo, las translaciones y rotaciones son solo los tipos que se usan en la práctica). Un origen de celdas es almacenado por el atributo “cellOrigin” y heredada por todas las subclases. El método CellGLO.getOrigin() devuelve el origen de celda, en forma de una instancia de la clase Matrix4d. Una celda también tiene unos límites, representados por los límites de java 3d, que describe su extensión física. Las subclases de CellGLO gestiona los limites de las celdas, mediante el método CellGLO.getBounds().

4.3.2 Parentesco entre celdas (celdas padre e hijo)

Un conjunto de celdas padre y con cero o más hijos son almacenados en un conjunto. Añadir y borrar celdas padre se hace mediante los métodos CellGLO.addParentCell() y CellGLO.removeParentCell() respectivamente. El método CellGLO.getParentCellIDs() devuelve un array de las instancias de la clase CellID, cada posición identifica una celda padre. Los métodos CellGLO.addChildCell() y CellGLO.removeChildCell() añade y borra los hijos de una celda. El método CellGLO.getChildren() devuelve una lista de los hijos de la celda. Al mismo tiempo , algunas celdas hijo pueden ser invisibles, que están condicionadas al cumplimiento de algunos límites visibles. El método CellGLO.getVisibleCells() devuelve una lista de celdas hijo que son visibles dado un cierto límite. Normalmente los límites visibles dependen de la visualización del frustum (El Frustum es el volumen de visualización de una cámara en un punto determinado, el cual está generado a partir de una matriz de proyección en perspectiva. Tiene forma de pirámide con la punta recortada) del avatar.

4.3.3 Comunicación inter-cliente vía una celda

Las celdas también tienen un mecanismo de comunicación entre clientes, usando el mecanismo de canal del proyecto Darkstar. Cada celda puede tener un simple canal de comunicación, identificado por un único nombre y creado mediante el método CellGLO.openCellChannel(). El método CellGLO.getCellChannel() devuelve el canal de la celda. Los clientes son añadidos como escuchantes del canal mediante le método CellGLO.addUserToCellChannel() y borrados con el método CellGLO.removeUserFromCellChannel(). Cada uno de los métodos anteriores necesita un identificador único de la sesión del cliente como argumento. (Véase la sección 6 para más información de la arquitectura de comunicación en el proyecto WonderLand).

4.3.4 Clases celda desde el lado del cliente y configuración

Cada clase CellGLO en el servidor se corresponde con una clase org.jdesktop.lg3d.wonderland.darkstar.client.cell.Cell en el cliente, el cuál es responsable de renderizar la celda. El nombre de la “cell class” del cliente es definida por cada una de las subclases individualmente por los clientes mediante el método CellGLO.getClientCellClassName(). En el lado del servidor CellGLO comunica su contenido visual y otros datos de configuración mediante una instancia de una clase que implementa la interface org.jdesktop.lg3d.wonderland.darkstar.common.CellSetup. Esto es devuelto desde el método CellGLO.getSetupData() y está implementado, por cada una de las subclases CellGLO del cliente. La interface CellSetup es simplemente una interface vacía, la cual extiende (hereda) la interface java.io.Serializable con el fin de poder ser enviado mediante serialización. En el lado del servidor cada clase CellGLO define su propia clase “setup” que implementa la interface CellSetup. Existen ejemplos, en el paquete: org.jdesktop.lg3d.wonderland.darkstar.common.setup incluye AnimatedCellSetup, AvatarCellSetup, ModelViewerCellSetup, SharedApp2DCellSetup, SimpleCellSetup y SlideShowCellSetup. Por ejemplo,la clase org.jdesktop.lg3d.wonderland.darkstar.common.SimpleCellSetup es utilizada, por una celda terreno simple y tiene métodos que devuelven el nombre de los archivos almacenados en el disco de la escena.

4.4 Cacheado de celda en el lado del Servidor

El conjunto de Cells que pueden estar almacenadas en memoria, en un momento dado por el cliente es gestionado por el servidor mediante una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.server.cell.UserCellCacheGLO existe una instancia de esta clase por cada usuario ( que es equivalente a decir “cliente”) y es creada cuando el usuario se registra en el sistema. Todas las instancias de UserCellCacheGLO son gestionadas por la instancia la clase MasterCellCacheGLO que fue creada por WonderlandBoot (vease sección 4.1). Son objetos gestionados dentro de la infraestructura del proyecto Darkstar. En la parte del servidor las clases cacheadas soportan varios cambios de estado a las CellGLOs. Ellos son: celda creada, celda root creada, celda movida, celda borrada y añadir padre a la celda. Actualmente, el método UserCellCacheGLO.revalidate() tiene en cuenta a los CellGLOs que se encuentran actualmente visibles y añade los CellGLOs que son nuevos y borra de la memoria del cliente los que hace tiempo que no son visibles. Los cambios de estado de los CellGLOs son comunicados mediante un canal dedicado (llamado CELL_CACHE) asociado con la instancia la clase UserCellCacheGLO. Actualmente, los mensajes que son emitidos por este canal son instancias serializadas de la clase org.jdesktop.lg3d.wonderland.darkstar.common.messages.CellHierarchyMessage Las celdas visibles son determinadas por la posición del avatar. Su ángulo de visión está determinado por una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.common.AvatarBoundsManager mediante su método getProximityBounds(). Este método define el área de visibilidad como una esfera con un radio específico (AvatarBoundsManager.PROXIMITY_SIZE = 200.0) desde el centro del avatar.

5. La Arquitectura del cliente

5.1 La clase Main

La clase org.jdesktop.lg3d.wonderland.Main, como su nombre indica, implementa el método main() que arranca el cliente. Él inicializa el interface de usuario y lee las opciones de configuración desde un fichero externo, en formato XML. La inicialización de la conexión con el servidor es mediante la clase interna StartupListener, que implementa la interface Lg3dStartupListener, desde el proyecto Looking Glass este método listener's startupComplete(), es invocado cuando la inicialización de los gráficos se termina. A su vez, la implementación del método startupComplete(), muestra una ventana de registro (véase clase org.jdesktop.lg3d.wonderland.LoginDialog) que acepta información de registro desde el usuario. Él inicializa una conexión al servidor WonderLand e invoca el método Main.enableMainWindow() para activar el cliente WonderLand, es decir, la interface de usuario. Toda la comunicación con el servidor WonderLand, basado en Darkstar, es gestionado por una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.client.ChannelController (esto parece engañoso ya que parece decir que no se tiene control sobre los canales, sino que provee de un mecanismo directo cliente servidor?). Una nueva conexión al servidor es iniciada con el método ChannelController.initCommunications(). Véase la sección 6 para más detalles de la clase ChannelController.

5.2 Universo Wonderland

El “universo”, es creado por una instancia de la clase org.jdesktop.lg3d.wonderland.scenemanager.WonderlandUniverseFactory, crea el java.awt.Canvas principal e inicializa algunos parámetros básicos de visualización. Está instancia es creada por una instancia de la clase org.jdesktop.lg3d.wonderland.scenemanager.WonderlandPlatformConfig, que a su vez, está especificada por la propiedad lg.platformConfigClass.

5.3 Gestor de escena

El proyecto WonderLand define su propio gestor de escena, el equivalente a un gestor de ventanas del sistema X Window en el proyecto Looking Glass. La clase org.jdesktop.lg3d.wonderland.scenemanager.WonderlandSceneManager extiende la clase LG3D SceneManagerBase, una clase abstracta que implementa la interface LG3D SceneManager. La clase LG3D SceneManagerBase maneja la comunicación con el servidor de visualización LG3D (el equivalente al Servidor X Windows) a través de su implementación de la interface LG3D DisplayServerManagerInterface. El método WonderlandSceneManager.initialize() contiene la mayor parte de la funcionalidad de esta clase.

El crea una instancia de la clase org.jdesktop.lg3d.wonderland.scenemanager.WorldController y una instancia de la clase Java 3D BranchGroup a la que el WorldController enlaza la totalidad de los contenidos visuales. Asimismo, agrega a la clase Java 3D BranchGroup como un hijo del servidor raíz de visualización LG3D. La instancia de WonderlandSceneManager también crea una instancia de una clase LG3D la StandardAppContainer, usando el gestor de layout null-style. La implementación de los métodos SceneManager.addFrame3D() y SceneManager.removeFrame3D() añade y borra el frame de la instancia de la clases StandardAppContainer. La utilidad esta poco clara actualmente?. La instancia de la clase WonderlandSceneManger está instalada de acuerdo a la especificación LG3D siguiente: El método createSceneManager() org.jdesktop.lg3d.wonderland.scenemanager.WonderlandConfigControl devuelve una instancia de la clase WonderlandSceneManager. La clase Main establece la propiedad "lg.configclass" a "org.jdesktop.lg3d.wonderland.scenemanager.WonderlandConfigControl". Información adicional de configuración para el gestor de escena también es manejada por la clase WonderlandConfigControl, la cual lee fichero XML de opciones de configuración, por defecto: "/org/jdesktop/lg3d/wonderland/scenemanager/resources/wonderland.lgcfg"

5.4 Controlador del mundo

La instancia de la clase WorldController maneja todo el el contenido visible en el mundo de Wonderland. Como miembros de la clase, ella mantiene instancias de 2 importantes clases del lado del cliente: org.jdesktop.lg3d.wonderland.scenemanager.UserCellCache and ChannelController. La WorldController toma como argumento de la BranchGroup Java 3D el que añade la iluminación: una de luz de ambiente de color RGB = {0.7, 0.7, 0.7}, y dos luces direcionales. Una luz direcional es blanca y es hacía abajo a la izquierda. La segunda luz direcional es RGB = {0.2, 0.2, 0.3} y está arriba a la izquierda.

5.5 Cacheado de celdas desde el cliente

Las celdas visibles cacheadas y gestionadas por una instancia de la UserCellCache. La carga/descarga de celdas y los cambios de su estado es controlado en su totalidad por el servidor a través del envío de mensajes desde el servidor al cliente, formateado como instancias de la clase CellHierarchyMessage. El método UserCellCache.handleMessage() maneja estos eventos del servidor, envía sobre un canal de comunicación gestionado por la infraestructura del Proyecto Darkstar y manjeado por una instancias de la clase org.jdesktop.lg3d.wonderland.darkstar.client.UserCellCacheChannelListener Una operación común, particularmente asignada al arranque del cliente, es la solicitud de crear nuevas celdas en el lado del cliente mediante un mensaje del tipo CellHierarchyMessage.LOAD_CELL.Usando la información de configuración incluida en el CellHiearchyMessage, una instancia de la clase celda del lado del cliente se crea al inicializar. La nueva celda es añadida a la cache HashMap de las celdas, y el hilo (una instancia de la clase interna CellUpdateThread dentro de la clase UserCellCache es registrado para actualizar el conjunto de celdas visibles para renderizar (la variable UserCellCache.visibleCells). La instancia de la clase UserCellCache también gestiona la lista de celdas en las que el avatar esta actualmente posicionado mediante la variable UserCellCache.avatarInCells (un HashSet). Este conjunto es actualizado con el hilo CellUpdateThread. Los eventos de entrada y salida de celda son generados - representados por las clases CellEnterEvent y CellExitEvent (en el paquete org.jdesktop.lg3d.wonderland.scenemanager.events), respectivamente-y enviados. La clase UserCellCache actualmente solo implementa un subconjunto de estados de celda: VISIBLE e INACTIVE. Los demás estados de celda no son manejados y son: ACTIVE, DISK y BOUNDS. La clase UserCellCache también implementa la interface org.jdesktop.lg3d.wonderland.scenemanager.UserMotionListener que recibe notificación cuando el avatar se mueve (mediante el metodo userMoved()). La implementacion del método UserCellCache.userMoved() actualmente es básico: el simplemente actualiza el estado visible de las celdas y genera mensajes de entrada/salida usando la posición actualizada del avatar.

6. Comunicación Cliente Servidor

Esta sección trata de los canales de comunicación y de los mensajes enviados entre el cliente WonderLand y el servidor, y entre los clientes. Cada cliente esta representado en el servidor por un número de objetos. Los objetos son:

  • UserGLO – Información básica del usuario, como nombre y color preferido
  • AvatarCellGLO – La celda donde el avatar del usuario esta renderizado
  • UserCellCacheGLO – Las celdas que son visibles a un determinado usuario.
Hay uno de estos objetos por cada uno de los usuarios/clientes. A medida que el usuario se mueve alrededor del mundo, el servidor rastrea que pistas conoce el usuario. Cuando el usuario se mueve, el notifica al servidor y el servidor examina la UserCellCacheGLO y comprueba si el cliente ya esta cargado en todas las celdas cercanas. Si el servidor encuentra una celda que el cliente no ha mirado aún, él le envía un mensaje, indicando al cliente la carga de la nueva celda.

6.1 Comunicación directa Cliente-Servidor

Cuando un cliente se conecta al servidor, se establece un enlace directo de comunicación cliente-servidor debido al Proyecto Darkstar.

El servidor transmite los siguientes mensajes al cliente, para ello utiliza el siguiente mecanismo

  1. Un mensaje inicial contiene la versión del protocolo de comunicación (en WonderlandBoot.loggedIn()).
  2. Los potenciales mensajes de error como instancias de la clase org.jdesktop.lg3d.wonderland.darkstar.common.messages.ErrorMessage (ídem, y también en WonderlandSessionListener.processFileTransferMessage().
  3. Instancias de la clase org.jdesktop.lg3d.wonderland.darkstar.common.messages.NativeApplicationMessage como los mensajes de respuesta al mensaje "create application cell" (en WonderlandSessionListener.processNativeApplicationMessage()).
  4. Instancias de la clase org.jdesktop.lg3d.wonderland.darkstar.common.messages.SoftphoneMessage (en los métodos callStatusChanged() y processSoftphoneMessage() del WonderlandSessionListener.

Estos son manejados por los clientes de la siguiente manera:

  1. La versión del protocolo y los mensajes de error son manejados por ChannelController.handleMessage().
  2. Los mensajes NativeApplicationMessage son manejados por el método receivedMessage() de la clase interna MessageListener de la clase org.jdesktop.lg3d.wonderland.appshare.ServerApp2DCell.
  3. Los mensajes SoftphoneMessage son también manejados por el ChannelController.handleMessage().

Un cliente transmite al servidor los siguientes mensajes , utilizando el mecanismo:

  1. Instancias de la clase NativeApplicationMessage. Estás son enviadas por el constructor de la clase. Esto son enviados por el constructor de la clase ServerApp2DCell y el método sendMessage() del ChannelController.
  2. Instancias de org.jdesktop.lg3d.wonderland.darkstar.common.messages.SoftphoneMessage. Estos son enviados por los métodos connectSoftphone() y disconnectSoftphone() del ChannelController.
  3. Instancias de org.jdesktop.lg3d.wonderland.darkstar.common.messages.AvatarSetupMessage inicializada por el método loggedIn() en la clase ChannelController.
  4. Instancias de alguna subclase de org.jdesktop.lg3d.wonderland.darkstar.common.messages.CellMessage. Actualmente parece que no hay ninguna.
El server recibe desde el cliente los siguientes mensajes, utilizando este mecanismo:
  1. Instancias de la clase NativeApplicationMessage. Estos son manejados por el método receivedMessage() de org.jdesktop.lg3d.wonderland.darkstar.server.WonderlandBaseSessionListener, y posteriormente por su método processNativeApplicationMessage().
  2. Instancias de SoftphoneMessage. Estos son manejados por el método receivedMessage() de WonderlandSessionListener.
  3. Instancias de mensajes org.jdesktop.lg3d.wonderland.darkstar.common.messages.AvatarSetupMessage. Estos son también manejados por el método receivedMessage() de WonderlandSessionListener.
  4. Otras instancias de algunas subclases org.jdesktop.lg3d.wonderland.darkstar.common.messages.CellMessage, enviados a las instancias de la clase org.jdesktop.lg3d.wonderland.darkstar.server.CellMessageListener.

6.2 Publicar / Suscribir canales de comunicación

El servidor WonderLand también crea canales de comunicación de publicar/suscribir, que incluye: USER_CHANGE, CELL_CACHE, AVATAR_P2P, AVATAR_CELL y SERVER_MANAGER_CHANNEL. Un canal proporciona un mecanismo de comunicación entre clientes y también entre un cliente y su servidor.

6.2.1 El canal USER_CHANGE

El canal de comunicación USER_CHANGE esta creado por WonderlandBoot en su método initialize(), y todos los nuevos clientes son añadidos automáticamente a él. Se usa exclusivamente para la comunicación servidor->cliente.

Sobre este canal, el servidor transmite a los clientes los mensajes siguientes:

  • Instancias de la clase org.jdesktop.lg3d.wonderland.darkstar.common.messages.UserChangedMessage cuando los usuarios son añadidos (USER_ADD, en el método processAvatarSetupMessage() de la clase WonderlandSessionListener) o cuando los usuarios lo dejan (USER_LEFT, en el método disconnected() de la clase WonderlandSessionListener).

En este canal, el servidor no recibe mensajes desde el cliente.

En este canal, el cliente no transmite mensajes.

El cliente maneja estos mensajes mediante el método receivedMessage() de la clase org.jdesktop.lg3d.wonderland.darkstar.client.UserChannelListener.

6.2.2 CELL_CACHE channels

El servidor crea un canal CELL_CACHE por cada cliente conectado. El nombre del canal tiene el formato: user + CELL_CACHE, donde “user” es el nombre del usuario. El canal CELL_CACHE para un cliente es creado por la instancia de la clase UserCellCacheGLO que corresponde al cliente (en su constructor). Cada nuevo cliente es automáticamente añadido a uno de estos canales.

Cada instancias de la clase UserCellCacheGLO tiene un canal CELL_CACHE. Sólo un cliente /usuario (la caché del usuario)está suscrito al canal CELL_CACHE. La suscripción es gestionada en el método login() de la clase UserCellCacheGLO. Este canal es usado exclusivamente para la comunicación del servidor->cliente.

El servidor transmite, sobre este canal, al cliente los mensajes siguientes. Los mensajes son enviados por la instancia de UserCellCacheGLO.

  • Mensajes de las instancias de la clase CellHiearchyMessage, que puden ser del tipo: LOAD_CELL, MOVE_CELL, CELL_INACTIVE, ADD_PARENT, REMOVE_PARENT, SET_WORLD_ROOT, y DELETE_CELL.

El servidor no recibe cualquier mensaje desde el cliente en este canal.

El cliente no transmite cualquier mensaje en este canal.

El cliente maneja estos mensajes mediante el método receivedMessage() una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.client.UserCellCacheChannelListener.

6.2.3 Canales AVATAR_P2P

El servidor crea un canal AVATAR_P2P, por cada cliente conectado. El nombre del canal es de la siguientes forma: user+AVATAAR_P2P, donde “user” es el nombre del usuario. Este canal es creado por una instancia de la clase AvatarCellGLO durante su construcción y por tanto gestionada por la instancia del AvatarCellGLO. Otro cliente puede solicitar unirse a clientes con canal P2P mediante el envío de mensajes AvatarCellMessage(JOIN_P2P) en el canal AVATAR_CELL (mirar lo siguiente).

Cada avatar envía su actualización de movimientos sobre el canal AVATAR_P2P de los clientes, de modo que cualquier cliente se preocupa de esas actualizaciones (generalmente cualquier otro cliente en el area de visualización del avatar) subscribiendose a las mismas.

El servidor transmite al cliente, sobre este canal, los mensajes siguientes:

  • Mensajes de la instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.common.messages.AvatarP2PMessage, de los que hay dos clases:
    • El mensaje SETUP es enviado por el método receivedMessage() de la clase AvatarCellGLO en respuesta a un mensaje AvatarCellMessage(JOIN_P2P).
    • El mensaje SPEAKING es enviado por los métodos callStatusChanged() y rocessAvatarCellMessage() de la clase WonderlandSessionListener y el método setSpeakingStatus() de la AvatarCellGLO.

Un cliente maneja mensajes mediante el método receivedMessage() que es de una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.client.AvatarP2PChannelListener.

Un cliente transmite instancias de la clase AvatarP2PMessage sobre este canal, aunque solo del tipo de mensajes MOVE and CHAT:

  • El mensaje MOVE es enviado por el método userMoved() de la clase org.jdesktop.lg3d.wonderland.scenemanager.avatar.Avatar en respuesta a una interacción del usuario.
  • El mensaje CHAT es enviado por le método sendChatMessage() de la clase Avatar.

El servidor actualmente recibe mensajes en este canal mediante el método handleMessage() que pertenece a una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.serverAvatarP2PChannelListenerGLO. (El método sólo es usado para propositos autenticación).

De esta manera, este canal es usado para intercomunicación con el cliente (para AvatarP2PMessages del tipo MOVE y CHAT), y para la comunicación servidor->cliente (para AvatarP2PMessages del tipo SETUP y SPEAKING).

6.2.4 Canales AVATAR_CELL

Un canal AVATAR_CELL es creado por una instancia de la clase AvatarCellGLO durante su construcción. El nombre de el canal tiene el formato: user + AVATAR_CELL donde 'usuario' es el nombre del usuario.

El servidor transmite al cliente, sobre este canal, los mensajes siguientes:

  • Una instancia de la clase AvatarCellMessage, que tiene un tipo básico: SETUP. Esto es enviado cuando un avatar se hace visible en una celda (por ejemplo: AvatarCellGLO)

Cuando es visible una celda, el server recorre la lista de todas las CellGLO's y añade el cliente al canal CellGLO's si el canal existe. Actualmente, solamente el avatar CellGLO crea un canal por si mismo. En ese momente, un mensaje SETUP es enviado al cliente, que guarda una referencia al canal para la comunicación futura.

El servidor transmite al cliente, sobre este canal, los mensajes siguientes:

  • Instancias de AvatarCellMessage. El maneja estos mensajes mediante el método receivedMessage() de una instancia de la clase AvatarCellGLO (para mensajes que son de tipo CELL_MOVE, CELL_ENTER, y CELL_EXIT) y también con el método receivedMessage() de una de instancia del WonderlandSessionListener (para mensajes que son del tipo AVATAR_MOVE, AVATAR_MUTE y JOIN_P2P).

El cliente transmite instancias de la clase AvatarCellMessage (vease org.jdesktop.lg3d.wonderland.darkstar.client.cell.AvatarCell.)

El cliente recibe mensajes a través de este canal. Son manejados mediante el método receivedMessage() de una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.client.cell.AvatarCellChannelListener.

6.2.5 El canal SERVER_MANAGER_CHANNEL

El canal de comunicación SERVER_MANAGER_CHANNEL, creado por una instancia de la clase org.jdesktop.lg3d.wonderland.darkstar.server.ServerManagerGLO, es usado para la gestión de la comunicación del servidor al cliente. Actualmente, el servidor propiamente dicho y un cliente especial (codificado con el nombre “ServerManager”) son añadidos a este canal.

El servidor transmite y recibe instancias de la clase org.jdesktop.lg3d.wonderland.darkstar.common.messages.ServerManagerMessage del cliente sobre este canal, que pueden ser de cuatro tipos STATUS, FULL_STATUS, CHANGE_UPDATE_INTERVAL, y SET_USER_LIMIT.

El único cliente del canal de comunicación SERVER_MANAGER_CHANNEL es proporcionado por una instancia de la clase org.jdesktop.lg3d.wonderland.management.ManagerUI que se abre al ejecutar la etiqueta del Ant “Ant run-manager”.

6.3 Directrices para la gestión del cambio en el Cliente y el servidor

Hay una diferencia entre dos tipos de interacción con el usuario:

  1. Interacción del usuario que sólo cambia el estado del cliente, tal vez en términos de la aparición de una celda. Un ejemplo puede ser cuando el cursor de un usuario se sitúa sobre algo (mirar, por ejemplo el módulo simple).
  2. Una interacción de usuario que causa un cambio de estado de una CellGLO en el servidor. Un ejemplo puede ser cuando un usuario pulsa sobre algo.

En cada caso, de los descritos anteriormente, se asume que los cuatro clientes (C1, C2, C3 y C4) están conectados al servidor.

6.3.1 Cambio de estado del cliente

  1. Interacción del usuario con la celda del cliente C2 causa cambio de estado en la celda. (No cambio en el estado del servidor)
  2. La celdas actualizan su apariencia
  3. Un mensaje de difusión general se envía a los otros clientes por los canales de sus celdas; mensaje identificados “clase de cambio” y un nuevo estado de la celda.
  4. Otro clientes reciben mensajes y sus correspondientes actualizaciones de la apariencia de las celdas.

client change

6.3.2 Cambio de estado del servidor

  1. La interacción con la Cell en el cliente C2 causa un cambio de estado en CellGLO en el servidor
  2. Las actualizaciones del estado local de Cell (si es necesario) y de la apariencia
  3. El cliente C2 envía mensajes directos al servidor. El mensaje describe “clase de cambio” y el nuevo estado de Cell.
  4. El servidor identifica a la apropiada CellGLO
  5. CellGLO actualiza su estado
  6. El server envía mensajes de difusión (broadcasts) en el canal de Cell a todos los clientes excepto al cliente original. El mensaje describe “clase de cambio” y el nuevo estado de Cell.
  7. Cada cliente recibe mensajes y actualizaciones de estado de Cell ( si es necesario) y de su apariencia.

server change

El flujo de control de arriba difiere del Modelo Vista Controlador (MVC) convencional en las siguientes características:

  1. No hay una clara separación entre el modelo y su vista. Un CellGLO determina su Cell ( lo que equivale a decir que el modelo determina su vista). Esto significa que no es posible usar la misma clase CellGLO para renderizar múltiples clases Cell. Por ejemplo, una clase CellGLO representando una posible muerte no tiene dos clases Cell que provean de diferentes renderizados de una muerte.
  2. No hay una clara separación entre el modelo y su vista. El controlador para una vista (siguiendo norma de Swing) , es realizado por una clase interna en las clases de la vista. Por ejemplo, un controlador para una Cell es a menudo proporcionado por una clase interna de la clase Cell.
  3. Debido a que múltiples clientes renderizan la misma Cell. Es necesario sincronizar entre los clientes. Este requisito esta fuera del MVC, y se utiliza en WonderLand para el uso de los mensajes del canal propio de una Cell.

Finalmente, el flujo de control en MVC difiere mucho en WonderLand. Por ejemplo, si WonderLand usará MVC, el flujo de control podría ser:

  1. La interacción del usuario con Cell en el cliente C2, causa un cambio de estado en CellGLO en el servidor.
  2. El cliente C2 envía un mensaje directamente al servidor. El mensaje describe “clase de cambio” y el nuevo estado de Cell.
  3. El servidor identifica a la apropiada CellGLO
  4. CellGLO actualiza su estado
  5. El server envía mensajes de difusión (broadcasts) en el canal de Cell a todos los clientes excepto al cliente original. El mensaje describe “clase de cambio” y el nuevo estado de Cell.
  6. Cada cliente recibe mensajes y respuestas del estado de la CellGLO.
  7. Cada cliente actualiza el estado de Cell (si es necesario) y su apariencia.

classic MVC

La razón de esta diferencia es por el rendimiento. Es importante que el usuario sea notificado de un cambio de apariencia tan rápido como sea posible (por ejemplo, antes de notificar el servidor).

7. Resumen de la importancia del código del flujo de secuencias

Esta sección resume el control de flujo en el código para dos aspectos del proyecto WonderLand: uno, cuando un cliente inicia la conexión y dos, cuando un avatar se mueve o cambia su punto de vista.

7.1 Secuencia de Código cuando un cliente inicia la conexión

  1. La clase Main crea la ventana principal y añade una instancia de la clase LG3D Lg3dConnector a la ventana principal. Esto, a su vez, arranca el visor servidor LG3D. Tras la inicialización, el visor servidor L3GD inicializa el universo, sistema de ventanas, vistas, crea la escena gráfica raíz (scene graph-vease java3D) y inicializa el gestor de escena.
  2. El gestor de escena (Scene Manager), crea una nueva instancia de la clase WorldController, el cuál crea una nuevas instancias de las clases ChannelController y UserCellCache.
  3. Una vez completada la inicialización del LG3D, el método StartupListener.startupComplete() es invocado lo que provoca la ventana de autenticación del WonderLand.
  4. Una vez confirmado el registro de usuario, una conexión al servidor Darkstar es abierta. El cliente espera por la confirmación del registro, la cuál es enviada de forma asíncrona mediante una llamada al WonderlandClientListener.loggedIn().
  5. Concluida la autenticación, el cliente envía un mensaje AvatarSetupMessage al servidor Darkstar mediante su mecanismo de comunicación cliente-servidor con información sobre el avatar, tal como su modelo visual.
  6. Una vez concluido el proceso de registro, la ventana principal del cliente WonderLand es activada.

7.2 Secuencia de Código cuando se inicia el Servidor

  1. El método WonderLandBoot.initialize() crea nuevas instancias de las clases ServerManagerGLO, UserManager, MasterCellCacheGLO y ChecksumManagerGLO. Un canal Publicar/suscribir también se crea y se llama USER_CHANGE.
  2. La instancia MasterCellCacheGLO crea una nueva instancia de la clase WorldRootCellGLO. A su vez esta invoca al método WorldRootCellGLO.buildWorld() que crea todas las celdas del mundo.
  3. Una instancia de la clase WonderlandSessionListener recibe un mensaje AvatarSetupMenssage desde el cliente. El crea una nueva instancia de la clase UserGLO.
  4. La instancia UserGLO crea una nueva instancia AvatarCellGLO, que a su vez crea una nueva instancia UserCellCacheGLO.
  5. La instancia UserCellCacheGLO crea un canal publicar/suscribir llamado user+CELL_CACHE, donde 'user' es el nombre del usuario.
  6. La instancia AvatarCellGLO entonces abre un canal publicar/suscribir llamado AVATAR_P2P y un canal llamado user+AVATAR_TILE, donde 'user' es el nombre del usuario.
  7. La instancia WonderlandSessionListener entonces enlaza el cliente al canal USER_CHANGE y envía un mensaje UserChangedMessage (USER_ADDED) al cliente. Él entonces llama al método login() de la instancia UserGLO.
  8. El método UserGLO.login() añade una referencia del usuario al mapa hash (map hash) relacionando los ID's de los objetos de usuario. Invoca al AvatarCellGLO.login().
  9. El AvatarCellGLO.login() añade la instancia recibida del AvatarCellGLO a la instancia MasterCellCacheGLO. El entonces llama al UserCellCacheGLO.login() que une el cliente al usuario al canal user+CELL_CACHE , añade a sí mismo (el UserCellCacheGLO) a la instancia del MasterCellCacheGLO, y envía un mensaje CellHiearchyMessage (LOAD_CELL) al canal llamado “user+CELL_CACHE”, y entonces envía un mensaje CellHierarchyMessage (SET_WORLD_ROOT) al canal llamado “user+CELL_CACHE”.
  10. El método UserGLO.login() entonces llama al método UserCellCacheGLO.avatarCellMoved, que procesa la lista de celdas visibles y envía el mensaje CellHierarchyMessage (LOAD_CELL) a todas las celdas visibles en el canal llamado “user+CELL_CACHE”. También envía mensajes CellHierarchyMessage (DELETE_CELL o CELL_INACTIVE) para las celdas no visibles en el canal “user+CELL_CACHE”.
  11. Finalmente la WonderlandSessionListener envía los mensajes UserChangedMessage a cada cliente a través del canal USER_CHANGE para notificarles el nuevo cliente.

7.3 Secuencia de Código cuando un Avatar se Mueve

La secuencia de código que nosotros consideramos es cuando el usuario presiona una de las teclas de cursor para mover la posición del avatar.

  1. Los eventos del teclado son manejados por el método keyPressed() de la clase org.jdesktop.lg3d.wonderland.scenemanager.WalkBehavior. El estado de la instancia de la clase interna Stimulus es actualizado para reflejar la pulsación de las teclas.
  2. El método scheduleUpdate() de la instancia de la clase org.jdesktop.lg3d.wonderland.scenemanager.AvatarControlBehavior es llamado y queda a la espera de actualizaciones de estado del avatar.
  3. El método AvatarControlBehavior.processStimulus() despierta y llama al método WalkBehavior.updateState() que actualiza la posición del avatar.
  4. La detección de colisiones es calculada en base a la nueva posición del Avatar. La posición de la cámara se actualiza.
  5. Todas las implementaciones del interface UserMotionListener son notificadas de la nueva posición del avatar mediante el método userMoved(). Un ejemplo de una implementación de la clase UserMotionListener es la clase UserCellCache, cuyo método userMoved() llama al método UserCellCache.updateCells(). (Otro ejemplo de implementación del interface es la clase AvatarCell).
  6. El método updateCells() procesa las celdas visibles basándose en la vista de “frustum” del usuario. Actualiza el estado de cada celda y la lista de celdas visibles. Para todas las celdas visibles, actualiza la lista de celdas del avatar que están actualmente en pie. Causa eventos del tipo CellEnterEvent y CellExitEvent para enviarse a las apropiadas celdas (dentro de los eventos del marco de trabajo del LG3D). (Al mismo tiempo el AvatarCellMessage escribe CELL_ENTER y CELL_EXIT no se envían al servidor, ni el servidor toma ninguna acción al recibir estos eventos).
  7. El método AvatarCell.userMoved() envía un AvatarCellMessage (AVATAR_MOVE y CELLMOVE) al servidor mediante el canal AVATAR_TILE. La posición del avatar es actualizada en el servidor y la UserCellCacheGLO se pregunta a si misma (lista de celdas visibles y invisibles, actualiza su estado e informa al cliente) .

8. Futuro del trabajo de documentación

Este documento de arquitectura del software describe lo básico del cliente-servidor del Wonderland. Es destacable la ausencia de documentación de Avatares, su configuración y comportamiento, compartición de aplicaciones y el audio.

Topic ProyectoWonderlandArquitectura . { Edit | Ref-By | Printable | Diffs r5 < r4 < r3 < r2 < r1 | More }
 XML java.net RSS

Revision r5 - 25 Jun 2008 - 16:42:37 - Main.nicer94
Parents: WebHome > ProjectWonderland