diff --git a/docs/whirled/design.txt b/docs/whirled/design.txt index f540a9459..8a60cc970 100644 --- a/docs/whirled/design.txt +++ b/docs/whirled/design.txt @@ -30,10 +30,6 @@ scene database, from which they can then continue to mirror updates as needed. * Notes -Scene provider needs to do the right thing when a client requests an out -of date scene. Presently it doesn't handle sending the client the updated -scene data. - Scene manager registers a timer when it becomes empty and flushes itself from memory after timeout period. diff --git a/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java b/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java index d29660b04..c6a218c5d 100644 --- a/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java +++ b/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java @@ -1,5 +1,5 @@ // -// $Id: DisplayMisoSceneImpl.java,v 1.42 2001/10/25 16:36:42 shaper Exp $ +// $Id: DisplayMisoSceneImpl.java,v 1.43 2001/11/12 20:56:55 mdb Exp $ package com.threerings.miso.scene; @@ -11,7 +11,6 @@ import java.util.List; import com.samskivert.util.StringUtil; import com.threerings.media.tile.*; -import com.threerings.whirled.data.Scene; import com.threerings.miso.Log; import com.threerings.miso.scene.util.ClusterUtil; diff --git a/src/java/com/threerings/miso/tools/xml/XMLSceneGroupParser.java b/src/java/com/threerings/miso/tools/xml/XMLSceneGroupParser.java index 900a15075..0c7ef995c 100644 --- a/src/java/com/threerings/miso/tools/xml/XMLSceneGroupParser.java +++ b/src/java/com/threerings/miso/tools/xml/XMLSceneGroupParser.java @@ -1,5 +1,5 @@ // -// $Id: XMLSceneGroupParser.java,v 1.7 2001/10/17 22:21:22 shaper Exp $ +// $Id: XMLSceneGroupParser.java,v 1.8 2001/11/12 20:56:55 mdb Exp $ package com.threerings.miso.scene.xml; @@ -15,8 +15,6 @@ import com.threerings.miso.Log; import com.threerings.miso.scene.*; import com.threerings.miso.scene.util.MisoSceneUtil; -import com.threerings.whirled.data.Scene; - /** * Parses an XML scene group description file, loads the referenced * scenes into the runtime scene repository, and creates bindings diff --git a/src/java/com/threerings/whirled/client/DisplayScene.java b/src/java/com/threerings/whirled/client/DisplayScene.java new file mode 100644 index 000000000..dd2cdb890 --- /dev/null +++ b/src/java/com/threerings/whirled/client/DisplayScene.java @@ -0,0 +1,45 @@ +// +// $Id: DisplayScene.java,v 1.1 2001/11/12 20:56:55 mdb Exp $ + +package com.threerings.whirled.client; + +import com.threerings.crowd.data.PlaceConfig; + +/** + * This interface makes available the scene information that is needed by + * a client to display a scene. At this basic level, not much information + * is available, but extensions to this interface begin to create a more + * comprehensive picture of a scene in a system built from the Whirled + * services. + * + *
Additionally, at this basic level, the DisplayScene
+ * does not differ greatly (or at all) from the {@link
+ * com.threerings.whirled.server.RuntimeScene} interface, but the
+ * distinction provides a mechanism for handling the more substantial
+ * differences that appear in more sophisticated extensions to the base
+ * scene services.
+ */
+public interface DisplayScene
+{
+ /**
+ * Returns the unique identifier for this scene.
+ */
+ public int getId ();
+
+ /**
+ * Returns the version number of this scene.
+ */
+ public int getVersion ();
+
+ /**
+ * Returns the list of scene ids of this scene's neighbors.
+ */
+ public int[] getNeighborIds ();
+
+ /**
+ * Returns the place config that can be used to determine which place
+ * controller instance should be used to display this scene as well as
+ * to obtain runtime configuration information.
+ */
+ public PlaceConfig getPlaceConfig ();
+}
diff --git a/src/java/com/threerings/whirled/client/DisplaySceneFactory.java b/src/java/com/threerings/whirled/client/DisplaySceneFactory.java
new file mode 100644
index 000000000..9ee977c3f
--- /dev/null
+++ b/src/java/com/threerings/whirled/client/DisplaySceneFactory.java
@@ -0,0 +1,24 @@
+//
+// $Id: DisplaySceneFactory.java,v 1.1 2001/11/12 20:56:55 mdb Exp $
+
+package com.threerings.whirled.client;
+
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.whirled.data.SceneModel;
+
+/**
+ * When resolving a scene, the scene director loads a scene model from the
+ * scene repository, but it needs an external entity to convert that scene
+ * model into the appropriate implementation of {@link DisplayScene}. The
+ * display scene factory interface provides the mechanism by which users
+ * of the Whirled system can create the appropriate instances.
+ */
+public interface DisplaySceneFactory
+{
+ /**
+ * This is called by the scene director after it has loaded the scene
+ * model from the scene repository and obtained the place config from
+ * a successful moveTo request.
+ */
+ public DisplayScene createScene (SceneModel model, PlaceConfig config);
+}
diff --git a/src/java/com/threerings/whirled/client/DisplaySceneImpl.java b/src/java/com/threerings/whirled/client/DisplaySceneImpl.java
new file mode 100644
index 000000000..448a10759
--- /dev/null
+++ b/src/java/com/threerings/whirled/client/DisplaySceneImpl.java
@@ -0,0 +1,54 @@
+//
+// $Id: DisplaySceneImpl.java,v 1.1 2001/11/12 20:56:55 mdb Exp $
+
+package com.threerings.whirled.client;
+
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.whirled.data.SceneModel;
+
+/**
+ * A basic implementation of the {@link DisplayScene} interface which is
+ * used by default if no extended implementation is desired.
+ */
+public class DisplaySceneImpl implements DisplayScene
+{
+ /**
+ * Creates an instance that will obtain data from the supplied scene
+ * model and place config.
+ */
+ public DisplaySceneImpl (SceneModel model, PlaceConfig config)
+ {
+ _model = model;
+ _config = config;
+ }
+
+ // documentation inherited
+ public int getId ()
+ {
+ return _model.sceneId;
+ }
+
+ // documentation inherited
+ public int getVersion ()
+ {
+ return _model.version;
+ }
+
+ // documentation inherited
+ public int[] getNeighborIds ()
+ {
+ return _model.neighborIds;
+ }
+
+ // documentation inherited
+ public PlaceConfig getPlaceConfig ()
+ {
+ return _config;
+ }
+
+ /** A reference to our scene model. */
+ protected SceneModel _model;
+
+ /** A reference to our place configuration. */
+ protected PlaceConfig _config;
+}
diff --git a/src/java/com/threerings/whirled/client/SceneCodes.java b/src/java/com/threerings/whirled/client/SceneCodes.java
index 477b9f376..85a6153fa 100644
--- a/src/java/com/threerings/whirled/client/SceneCodes.java
+++ b/src/java/com/threerings/whirled/client/SceneCodes.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneCodes.java,v 1.2 2001/10/11 04:07:54 mdb Exp $
+// $Id: SceneCodes.java,v 1.3 2001/11/12 20:56:55 mdb Exp $
package com.threerings.whirled.client;
@@ -12,4 +12,11 @@ public interface SceneCodes extends LocationCodes
{
/** The module name for the scene services. */
public static final String MODULE_NAME = "whirled!scene";
+
+ /** The response identifier for a successful moveTo request that
+ * includes an updated scene model. This is mapped by the invocation
+ * services to a call to {@link
+ * SceneDirector#handleMoveSucceededPlusUpdate}. */
+ public static final String MOVE_SUCCEEDED_PLUS_UPDATE_RESPONSE =
+ "MoveSucceededPlusUpdate";
}
diff --git a/src/java/com/threerings/whirled/client/SceneController.java b/src/java/com/threerings/whirled/client/SceneController.java
new file mode 100644
index 000000000..9756a3fc1
--- /dev/null
+++ b/src/java/com/threerings/whirled/client/SceneController.java
@@ -0,0 +1,18 @@
+//
+// $Id: SceneController.java,v 1.1 2001/11/12 20:56:55 mdb Exp $
+
+package com.threerings.whirled.client;
+
+import com.threerings.crowd.client.PlaceController;
+
+/**
+ * The base scene controller class. It is expected that users of the
+ * Whirled services will extend this controller class when creating
+ * specialized controllers for their scenes. Presently there are no basic
+ * scene services provided by this controller, but its existence affords
+ * the addition of such services should they become necessary in the
+ * future.
+ */
+public abstract class SceneController extends PlaceController
+{
+}
diff --git a/src/java/com/threerings/whirled/client/SceneDirector.java b/src/java/com/threerings/whirled/client/SceneDirector.java
index 3d491b3e2..15e52d35c 100644
--- a/src/java/com/threerings/whirled/client/SceneDirector.java
+++ b/src/java/com/threerings/whirled/client/SceneDirector.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneDirector.java,v 1.6 2001/10/11 04:07:54 mdb Exp $
+// $Id: SceneDirector.java,v 1.7 2001/11/12 20:56:55 mdb Exp $
package com.threerings.whirled.client;
@@ -16,43 +16,50 @@ import com.threerings.crowd.data.PlaceObject;
import com.threerings.whirled.Log;
import com.threerings.whirled.client.persist.SceneRepository;
+import com.threerings.whirled.data.SceneModel;
import com.threerings.whirled.util.NoSuchSceneException;
-import com.threerings.whirled.data.Scene;
import com.threerings.whirled.util.WhirledContext;
/**
* The scene director is the client's interface to all things scene
* related. It interfaces with the scene repository to ensure that scene
* objects are available when the client enters a particular scene. It
- * handles moving from scene to scene (it extends and replaces the
- * location director in order to do this).
+ * handles moving from scene to scene (it extends and replaces the {@link
+ * LocationDirector} in order to do this).
*
*
Note that when the scene director is in use instead of the location
* director, scene ids instead of place oids will be supplied to {@link
- * com.threerings.crowd.client.LocationObserver#locationMayChange}
- * and {@link
- * com.threerings.crowd.client.LocationObserver#locationChangeFailed}.
+ * LocationObserver#locationMayChange} and {@link
+ * LocationObserver#locationChangeFailed}.
*/
public class SceneDirector
extends LocationDirector implements SceneCodes
{
/**
* Creates a new scene director with the specified context.
+ *
+ * @param ctx the active client context.
+ * @param screp the entity from which the scene director will load
+ * scene data from the local client scene storage.
+ * @param dsfact the factory that knows which derivation of {@link
+ * DisplayScene} to create for the current system.
*/
- public SceneDirector (WhirledContext ctx, SceneRepository screp)
+ public SceneDirector (WhirledContext ctx, SceneRepository screp,
+ DisplaySceneFactory dsfact)
{
super(ctx);
// we'll need these for later
_ctx = ctx;
_screp = screp;
+ _dsfact = dsfact;
}
/**
- * Returns the scene object associated with the scene we currently
- * occupy or null if we currently occupy no scene.
+ * Returns the dispaly scene object associated with the scene we
+ * currently occupy or null if we currently occupy no scene.
*/
- public Scene getScene ()
+ public DisplayScene getScene ()
{
return _scene;
}
@@ -86,10 +93,10 @@ public class SceneDirector
// load up the pending scene so that we can communicate it's most
// recent version to the server
int sceneVers = 0;
- _pendingScene = loadScene(sceneId);
+ _pendingModel = loadSceneModel(sceneId);
// if we were unable to load it, assume a previous version of zero
- if (_pendingScene != null) {
- sceneVers = _pendingScene.getVersion();
+ if (_pendingModel != null) {
+ sceneVers = _pendingModel.version;
}
// make a note of our pending scene id
@@ -113,22 +120,54 @@ public class SceneDirector
// parallelize and go ahead and load up the new scene now rather
// than wait until subscription to our place object succeeds
- // release the old scene
- releaseScene(_scene);
-
- // update our scene id tracking fields
+ // keep track of our previous scene info
_previousSceneId = _sceneId;
+
+ // clear out the old info
+ clearScene();
+
+ // make the pending scene the active scene
_sceneId = _pendingSceneId;
_pendingSceneId = -1;
- // and load the new scene
- _scene = loadScene(_sceneId);
+ // load the new scene model
+ _model = loadSceneModel(_sceneId);
// complain if we didn't find a scene
- if (_scene == null) {
+ if (_model == null) {
Log.warning("Aiya! Unable to load scene [sid=" + _sceneId +
", plid=" + placeId + "].");
}
+
+ // and finally create a display scene instance with the model and
+ // the place config
+ _scene = _dsfact.createScene(_model, config);
+ }
+
+ /**
+ * Called in response to a successful moveTo request when
+ * our cached scene was out of date and the server determined that we
+ * needed an updated copy.
+ */
+ public void handleMoveSucceededPlusUpdate (
+ int invid, int placeId, PlaceConfig config, SceneModel model)
+ {
+ // update the model in the repository
+ try {
+ _screp.updateSceneModel(model);
+ } catch (IOException ioe) {
+ Log.warning("Danger Will Robinson! We were unable to update " +
+ "our scene cache with a new version of a scene " +
+ "provided by the server " +
+ "[newVersion=" + model.version + "].");
+ Log.logStackTrace(ioe);
+ }
+
+ // update our scene cache
+ _scache.put(model.sceneId, model);
+
+ // and pass through to the normal move succeeded handler
+ handleMoveSucceeded(invid, placeId, config);
}
/**
@@ -144,13 +183,17 @@ public class SceneDirector
notifyFailure(sceneId, reason);
}
+ /**
+ * Called when something breaks down in the process of performing a
+ * moveTo request.
+ */
protected void recoverFailedMove (int placeId)
{
- // clear out our now bogus scene tracking info
+ // we'll need this momentarily
int sceneId = _sceneId;
- _sceneId = -1;
- releaseScene(_scene);
- _scene = null;
+
+ // clear out our now bogus scene tracking info
+ clearScene();
// if we were previously somewhere (and that somewhere isn't where
// we just tried to go), try going back to that happy place
@@ -159,20 +202,37 @@ public class SceneDirector
}
}
+ /**
+ * Clears out our current scene information and releases the scene
+ * model for the loaded scene back to the cache.
+ */
+ protected void clearScene ()
+ {
+ // clear out our scene id info
+ _sceneId = -1;
+
+ // release the old scene model
+ releaseSceneModel(_model);
+
+ // clear out our references
+ _model = null;
+ _scene = null;
+ }
+
/**
* Loads a scene from the repository. If the scene is cached, it will
* be returned from the cache instead.
*/
- protected Scene loadScene (int sceneId)
+ protected SceneModel loadSceneModel (int sceneId)
{
- // first look in the cache
- Scene scene = (Scene)_scache.get(sceneId);
+ // first look in the model cache
+ SceneModel model = (SceneModel)_scache.get(sceneId);
// load from the repository if it's not cached
- if (scene == null) {
+ if (model == null) {
try {
- scene = _screp.loadScene(sceneId);
- _scache.put(sceneId, scene);
+ model = _screp.loadSceneModel(sceneId);
+ _scache.put(sceneId, model);
} catch (NoSuchSceneException nsse) {
// nothing special here, just fall through and return null
@@ -184,34 +244,46 @@ public class SceneDirector
}
}
- return scene;
+ return model;
}
/**
- * Unloads a scene that was previously loaded via {@link #loadScene}.
- * The scene will probably continue to live in the cache for a while
- * in case we quickly return to it.
+ * Unloads a scene model that was previously loaded via {@link
+ * #loadSceneModel}. The model will probably continue to live in the
+ * cache for a while in case we quickly return to it.
*/
- protected void releaseScene (Scene scene)
+ protected void releaseSceneModel (SceneModel model)
{
// we're cool if we're called with null
- if (scene == null) {
+ if (model == null) {
return;
}
}
+ /** Access to general client services. */
protected WhirledContext _ctx;
+
+ /** The entity via which we load scene data. */
protected SceneRepository _screp;
+
+ /** The entity we use to create display scenes from scene models. */
+ protected DisplaySceneFactory _dsfact;
+
+ /** A cache of scene model information. */
protected HashIntMap _scache = new HashIntMap();
- /** The scene object of the scene we currently occupy. */
- protected Scene _scene;
+ /** The display scene object for the scene we currently occupy. */
+ protected DisplayScene _scene;
+
+ /** The scene model for the scene we currently occupy. */
+ protected SceneModel _model;
/** The id of the scene we currently occupy. */
protected int _sceneId = -1;
- /** Our most recent copy of the scene we're about to enter. */
- protected Scene _pendingScene;
+ /** Our most recent copy of the scene model for the scene we're about
+ * to enter. */
+ protected SceneModel _pendingModel;
/**
* The id of the scene for which we have an outstanding moveTo
diff --git a/src/java/com/threerings/whirled/client/persist/SceneRepository.java b/src/java/com/threerings/whirled/client/persist/SceneRepository.java
index 5a27f0773..708879ab0 100644
--- a/src/java/com/threerings/whirled/client/persist/SceneRepository.java
+++ b/src/java/com/threerings/whirled/client/persist/SceneRepository.java
@@ -1,42 +1,43 @@
//
-// $Id: SceneRepository.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
+// $Id: SceneRepository.java,v 1.3 2001/11/12 20:56:55 mdb Exp $
package com.threerings.whirled.client.persist;
import java.io.IOException;
-import com.threerings.whirled.data.Scene;
+import com.threerings.whirled.data.SceneModel;
import com.threerings.whirled.util.NoSuchSceneException;
/**
* The scene repository provides access to a persistent repository of
- * scene information. The scenes in the repository can be updated with
- * individual scenes fetched from the server as well as with new scene
+ * scene information. The scene models in the repository can be updated
+ * with scene data fetched from the server as well as with new scene
* bundles that are periodically distributed to bring all clients into
* sync with the latest snapshot of the scene database.
*
- * @see com.threerings.whirled.data.Scene
+ * @see SceneModel
*/
public interface SceneRepository
{
/**
- * Fetches the scene with the specified scene id.
+ * Fetches the mode for the scene with the specified scene id.
*
* @exception IOException thrown if an error occurs attempting to load
- * a scene.
+ * the scene data.
* @exception NoSuchSceneException thrown if no scene exists with the
* specified scene id.
*/
- public Scene loadScene (int sceneId)
+ public SceneModel loadSceneModel (int sceneId)
throws IOException, NoSuchSceneException;
/**
- * Updates the specified scene in the repository with the information
- * provided in the scene object.
+ * Updates this scene model in the repository. This is generally only
+ * called when the server has provided us with a newer version of a
+ * scene than we previously had in our local repository.
*
* @exception IOException thrown if an error occurs attempting to
- * update the scene.
+ * update the scene data.
*/
- public void updateScene (Scene scene)
+ public void updateSceneModel (SceneModel model)
throws IOException;
}
diff --git a/src/java/com/threerings/whirled/data/DefaultSceneConfig.java b/src/java/com/threerings/whirled/data/DefaultSceneConfig.java
new file mode 100644
index 000000000..1f2a0f49f
--- /dev/null
+++ b/src/java/com/threerings/whirled/data/DefaultSceneConfig.java
@@ -0,0 +1,32 @@
+//
+// $Id: DefaultSceneConfig.java,v 1.1 2001/11/12 20:56:55 mdb Exp $
+
+package com.threerings.whirled.data;
+
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.whirled.client.SceneController;
+
+/**
+ * The default scene config simply causes the default scene manager and
+ * controller to be created. A user of the Whirled services would most
+ * likely extend the default scene config.
+ *
+ *
Note that this place config won't even work on the client side + * because it instantiates a {@link SceneController} which is an abstract + * class. It is used only for testing the server side and as a placeholder + * in case standard scene configuration information is one day needed. + */ +public class DefaultSceneConfig extends PlaceConfig +{ + // documentation inherited + public Class getControllerClass () + { + return SceneController.class; + } + + // documentation inherited + public String getManagerClassName () + { + return "com.threerings.whirled.server.SceneManager"; + } +} diff --git a/src/java/com/threerings/whirled/data/DummyScene.java b/src/java/com/threerings/whirled/data/DummyScene.java deleted file mode 100644 index 23f272726..000000000 --- a/src/java/com/threerings/whirled/data/DummyScene.java +++ /dev/null @@ -1,41 +0,0 @@ -// -// $Id: DummyScene.java,v 1.7 2001/11/08 02:59:17 mdb Exp $ - -package com.threerings.whirled.data; - -import com.threerings.crowd.data.PlaceConfig; - -public class DummyScene implements Scene -{ - public DummyScene (int sceneId) - { - _sceneId = sceneId; - } - - public int getId () - { - return _sceneId; - } - - public int getVersion () - { - return 1; - } - - public String getName () - { - return "scene"; - } - - public int[] getNeighborIds () - { - return null; - } - - public PlaceConfig getPlaceConfig () - { - return null; - } - - protected int _sceneId; -} diff --git a/src/java/com/threerings/whirled/data/EditableScene.java b/src/java/com/threerings/whirled/data/EditableScene.java deleted file mode 100644 index 685ad2a7e..000000000 --- a/src/java/com/threerings/whirled/data/EditableScene.java +++ /dev/null @@ -1,22 +0,0 @@ -// -// $Id: EditableScene.java,v 1.3 2001/10/05 23:59:36 mdb Exp $ - -package com.threerings.whirled.data; - -/** - * The editable scene interface. This separate interface allows the - * ability to modify the scenes to be restricted only to code that needs - * such an ability. - */ -public interface EditableScene extends Scene -{ - /** - * Updates the scene's unique identifier. - */ - public void setId (int sceneId); - - /** - * Updates the scene's version. - */ - public void setVersion (int version); -} diff --git a/src/java/com/threerings/whirled/data/Scene.java b/src/java/com/threerings/whirled/data/Scene.java deleted file mode 100644 index 187197fec..000000000 --- a/src/java/com/threerings/whirled/data/Scene.java +++ /dev/null @@ -1,45 +0,0 @@ -// -// $Id: Scene.java,v 1.6 2001/10/11 04:07:54 mdb Exp $ - -package com.threerings.whirled.data; - -import com.threerings.crowd.data.PlaceConfig; - -/** - * The base scene interface. This encapsulates the minimum information - * needed about a scene in the Whirled system. - */ -public interface Scene -{ - /** - * Returns the scene's unique identifier. - */ - public int getId (); - - /** - * Returns the scene's version. The version should be updated every - * time the scene is modified and stored back to the repository. This - * allows a client to determine whether or not they need an updated - * version of the scene for their local cache. - */ - public int getVersion (); - - /** - * Returns the scene ids of all scenes that neighbor this scene. A - * neighboring scene is one to which the user can traverse from this - * scene and vice versa. - */ - public int[] getNeighborIds (); - - /** - * A scene is associated with a place on the server. Because the - * scenes are loaded on demand, the scene implementation must be able - * to provide a place config instance for each scene. This will allow - * the server to figure out what manager class to instantiate to - * manage the scene and all the client to figure out what controller - * class to instantiate to controll the scene. Additionally, it may - * contain runtime configuration information needed by the application - * using the Whirled services. - */ - public PlaceConfig getPlaceConfig (); -} diff --git a/src/java/com/threerings/whirled/data/SceneModel.java b/src/java/com/threerings/whirled/data/SceneModel.java new file mode 100644 index 000000000..248225a03 --- /dev/null +++ b/src/java/com/threerings/whirled/data/SceneModel.java @@ -0,0 +1,63 @@ +// +// $Id: SceneModel.java,v 1.1 2001/11/12 20:56:55 mdb Exp $ + +package com.threerings.whirled.data; + +import java.io.IOException; +import java.io.DataInputStream; +import java.io.DataOutputStream; + +import com.threerings.presents.io.Streamable; + +/** + * The scene model is the bare bones representation of the data for a + * scene in the Whirled system. From the scene model, one would create an + * instance of {@link com.threerings.whirled.server.RuntimeScene}, {@link + * com.threerings.whirled.client.DisplayScene} or {@link + * com.threerings.whirled.tools.EditableScene}. + * + *
The scene model is what is loaded from the scene repositories and + * what is transmitted over the wire when communicating scenes from the + * server to the client. + */ +public class SceneModel implements Streamable +{ + /** This scene's unique identifier. */ + public int sceneId; + + /** The version number of this scene. Versions are incremented + * whenever modifications are made to a scene so that clients can + * determine whether or not they have the latest version of a + * scene. */ + public int version; + + /** The scene ids of the scenes that neighbor this scene. A neighbor + * is a scene that can be entered from this scene. */ + public int[] neighborIds; + + // documentation inherited + public void writeTo (DataOutputStream out) + throws IOException + { + out.writeInt(sceneId); + out.writeInt(version); + int nlength = neighborIds.length; + out.writeInt(nlength); + for (int i = 0; i < nlength; i++) { + out.writeInt(neighborIds[i]); + } + } + + // documentation inherited + public void readFrom (DataInputStream in) + throws IOException + { + sceneId = in.readInt(); + version = in.readInt(); + int nlength = in.readInt(); + neighborIds = new int[nlength]; + for (int i = 0; i < nlength; i++) { + neighborIds[i] = in.readInt(); + } + } +} diff --git a/src/java/com/threerings/whirled/server/DefaultRuntimeSceneFactory.java b/src/java/com/threerings/whirled/server/DefaultRuntimeSceneFactory.java new file mode 100644 index 000000000..f13f733ba --- /dev/null +++ b/src/java/com/threerings/whirled/server/DefaultRuntimeSceneFactory.java @@ -0,0 +1,21 @@ +// +// $Id: DefaultRuntimeSceneFactory.java,v 1.1 2001/11/12 20:56:56 mdb Exp $ + +package com.threerings.whirled.server; + +import com.threerings.whirled.data.DefaultSceneConfig; +import com.threerings.whirled.data.SceneModel; + +/** + * The default runtime scene factory creates {@link RuntimeSceneImpl} + * instances with {@link DefaultSceneConfig} instances (which create the + * default scene manager and controller). + */ +public class DefaultRuntimeSceneFactory implements RuntimeSceneFactory +{ + // documentation inherited + public RuntimeScene createScene (SceneModel model) + { + return new RuntimeSceneImpl(model, new DefaultSceneConfig()); + } +} diff --git a/src/java/com/threerings/whirled/server/RuntimeScene.java b/src/java/com/threerings/whirled/server/RuntimeScene.java new file mode 100644 index 000000000..7ad010ec1 --- /dev/null +++ b/src/java/com/threerings/whirled/server/RuntimeScene.java @@ -0,0 +1,45 @@ +// +// $Id: RuntimeScene.java,v 1.1 2001/11/12 20:56:56 mdb Exp $ + +package com.threerings.whirled.server; + +import com.threerings.crowd.data.PlaceConfig; + +/** + * This interface makes available the scene information that is needed by + * the server to manage a scene. At this basic level, not much information + * is available, but extensions to this interface begin to create a more + * comprehensive picture of a scene in a system built from the Whirled + * services. + * + *
Additionally, at this basic level, the RuntimeScene
+ * does not differ greatly (or at all) from the {@link
+ * com.threerings.whirled.client.DisplayScene} interface, but the
+ * distinction provides a mechanism for handling the more substantial
+ * differences that appear in more sophisticated extensions to the base
+ * scene services.
+ */
+public interface RuntimeScene
+{
+ /**
+ * Returns the unique identifier for this scene.
+ */
+ public int getId ();
+
+ /**
+ * Returns the version number of this scene.
+ */
+ public int getVersion ();
+
+ /**
+ * Returns the list of scene ids of this scene's neighbors.
+ */
+ public int[] getNeighborIds ();
+
+ /**
+ * Returns the place config that can be used to determine which place
+ * controller instance should be used to display this scene as well as
+ * to obtain runtime configuration information.
+ */
+ public PlaceConfig getPlaceConfig ();
+}
diff --git a/src/java/com/threerings/whirled/server/RuntimeSceneFactory.java b/src/java/com/threerings/whirled/server/RuntimeSceneFactory.java
new file mode 100644
index 000000000..f32ff592d
--- /dev/null
+++ b/src/java/com/threerings/whirled/server/RuntimeSceneFactory.java
@@ -0,0 +1,29 @@
+//
+// $Id: RuntimeSceneFactory.java,v 1.1 2001/11/12 20:56:56 mdb Exp $
+
+package com.threerings.whirled.server;
+
+import com.threerings.whirled.data.SceneModel;
+
+/**
+ * When resolving a scene, the scene registry loads scene models from the
+ * scene repository, but it needs an external entity to convert those
+ * scene models into the appropriate implementation of {@link
+ * RuntimeScene}. The runtime scene factory interface provides the
+ * mechanism by which users of the Whirled system can create the
+ * appropriate instances.
+ */
+public interface RuntimeSceneFactory
+{
+ /**
+ * This is called by the scene registry after it has loaded the scene
+ * model from the scene repository. The factory implementation is
+ * required to know what derivation of {@link
+ * com.threerings.crowd.data.PlaceConfig} should go along with the
+ * supplied scene model in order to create a {@link RuntimeScene}
+ * implementation. The expectation is that such information is either
+ * static or can be obtained from the scene model provided to this
+ * method.
+ */
+ public RuntimeScene createScene (SceneModel model);
+}
diff --git a/src/java/com/threerings/whirled/server/RuntimeSceneImpl.java b/src/java/com/threerings/whirled/server/RuntimeSceneImpl.java
new file mode 100644
index 000000000..8dde2db34
--- /dev/null
+++ b/src/java/com/threerings/whirled/server/RuntimeSceneImpl.java
@@ -0,0 +1,54 @@
+//
+// $Id: RuntimeSceneImpl.java,v 1.1 2001/11/12 20:56:56 mdb Exp $
+
+package com.threerings.whirled.server;
+
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.whirled.data.SceneModel;
+
+/**
+ * A basic implementation of the {@link RuntimeScene} interface which is
+ * used by default if no extended implementation is desired.
+ */
+public class RuntimeSceneImpl implements RuntimeScene
+{
+ /**
+ * Creates an instance that will obtain data from the supplied scene
+ * model and place config.
+ */
+ public RuntimeSceneImpl (SceneModel model, PlaceConfig config)
+ {
+ _model = model;
+ _config = config;
+ }
+
+ // documentation inherited
+ public int getId ()
+ {
+ return _model.sceneId;
+ }
+
+ // documentation inherited
+ public int getVersion ()
+ {
+ return _model.version;
+ }
+
+ // documentation inherited
+ public int[] getNeighborIds ()
+ {
+ return _model.neighborIds;
+ }
+
+ // documentation inherited
+ public PlaceConfig getPlaceConfig ()
+ {
+ return _config;
+ }
+
+ /** A reference to our scene model. */
+ protected SceneModel _model;
+
+ /** A reference to our place configuration. */
+ protected PlaceConfig _config;
+}
diff --git a/src/java/com/threerings/whirled/server/SceneManager.java b/src/java/com/threerings/whirled/server/SceneManager.java
index 87514e4d4..38e07e2e1 100644
--- a/src/java/com/threerings/whirled/server/SceneManager.java
+++ b/src/java/com/threerings/whirled/server/SceneManager.java
@@ -1,32 +1,50 @@
//
-// $Id: SceneManager.java,v 1.7 2001/10/24 00:58:12 mdb Exp $
+// $Id: SceneManager.java,v 1.8 2001/11/12 20:56:56 mdb Exp $
package com.threerings.whirled.server;
-import com.threerings.crowd.chat.ChatMessageHandler;
-import com.threerings.crowd.chat.ChatService;
import com.threerings.crowd.server.PlaceManager;
+import com.threerings.whirled.data.SceneModel;
-import com.threerings.whirled.data.Scene;
-
+/**
+ * The scene manager extends the place manager and takes care of basic
+ * scene services. Presently that is little more than registering the
+ * scene manager with the scene registry so that the manager can be looked
+ * up by scene id in addition to place object id.
+ */
public class SceneManager extends PlaceManager
{
/**
- * Returns the scene object (not the scene distributed object)
- * associated with this scene.
+ * Returns the runtime scene object (not the scene distributed object)
+ * being managed by this scene manager.
*/
- public Scene getScene ()
+ public RuntimeScene getScene ()
{
return _scene;
}
+ /**
+ * Returns a reference to the scene model from which we created our
+ * runtime scene object. This model must reflect any modifications
+ * this manager may have made to it in the course of managing the
+ * scene as it will be provided to the client as the definitive
+ * version of the scene. (The scene manager is responsible for writing
+ * changes made to the scene model back to the scene repository.)
+ */
+ public SceneModel getSceneModel ()
+ {
+ return _model;
+ }
+
/**
* Called by the scene registry once the scene manager has been
* created (and initialized), but before it is started up.
*/
- protected void postInit (Scene scene, SceneRegistry screg)
+ protected void postInit (
+ RuntimeScene scene, SceneModel model, SceneRegistry screg)
{
_scene = scene;
+ _model = model;
_screg = screg;
}
@@ -41,11 +59,6 @@ public class SceneManager extends PlaceManager
// let the scene registry know that we're up and running
_screg.sceneManagerDidStart(this);
-
- // register a chat message handler because we want to support
- // chatting
- MessageHandler handler = new ChatMessageHandler();
- registerMessageHandler(ChatService.SPEAK_REQUEST, handler);
}
/**
@@ -66,6 +79,17 @@ public class SceneManager extends PlaceManager
buf.append(", scene=").append(_scene);
}
- protected Scene _scene;
+ /** A reference to our runtime scene implementation which provides a
+ * meaningful interpretation of the data in the scene model. */
+ protected RuntimeScene _scene;
+
+ /** A reference to the scene model which we keep around because we may
+ * have to send it to clients that need updated versions of the model
+ * or to update the scene model in the repository if we modify the
+ * scene for some reason. */
+ protected SceneModel _model;
+
+ /** A reference to the scene registry so that we can call back to it
+ * when we're fully initialized. */
protected SceneRegistry _screg;
}
diff --git a/src/java/com/threerings/whirled/server/SceneProvider.java b/src/java/com/threerings/whirled/server/SceneProvider.java
index d08c17eeb..f47c97b28 100644
--- a/src/java/com/threerings/whirled/server/SceneProvider.java
+++ b/src/java/com/threerings/whirled/server/SceneProvider.java
@@ -1,16 +1,19 @@
//
-// $Id: SceneProvider.java,v 1.4 2001/10/11 04:07:54 mdb Exp $
+// $Id: SceneProvider.java,v 1.5 2001/11/12 20:56:56 mdb Exp $
package com.threerings.whirled.server;
import com.threerings.presents.server.InvocationProvider;
import com.threerings.presents.server.ServiceFailedException;
-import com.threerings.crowd.data.*;
+import com.threerings.crowd.data.BodyObject;
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.server.LocationProvider;
import com.threerings.whirled.Log;
import com.threerings.whirled.client.SceneCodes;
+import com.threerings.whirled.data.SceneModel;
/**
* The scene provider handles the server side of the scene related
@@ -72,10 +75,17 @@ public class SceneProvider
PlaceConfig config = LocationProvider.moveTo(source, ploid);
// check to see if they need a newer version of the scene data
+ SceneModel model = scmgr.getSceneModel();
+ if (sceneVersion < model.version) {
+ // then send the moveTo response
+ sendResponse(source, invid, MOVE_SUCCEEDED_PLUS_UPDATE_RESPONSE,
+ new Integer(ploid), config, model);
- // then send the moveTo response
- sendResponse(source, invid, MOVE_SUCCEEDED_RESPONSE,
- new Integer(ploid), config);
+ } else {
+ // then send the moveTo response
+ sendResponse(source, invid, MOVE_SUCCEEDED_RESPONSE,
+ new Integer(ploid), config);
+ }
} catch (ServiceFailedException sfe) {
sendResponse(source, invid, MOVE_FAILED_RESPONSE,
diff --git a/src/java/com/threerings/whirled/server/SceneRegistry.java b/src/java/com/threerings/whirled/server/SceneRegistry.java
index b654e0143..b14eca51b 100644
--- a/src/java/com/threerings/whirled/server/SceneRegistry.java
+++ b/src/java/com/threerings/whirled/server/SceneRegistry.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneRegistry.java,v 1.9 2001/11/09 21:47:09 mdb Exp $
+// $Id: SceneRegistry.java,v 1.10 2001/11/12 20:56:56 mdb Exp $
package com.threerings.whirled.server;
@@ -13,7 +13,7 @@ import com.threerings.crowd.server.CrowdServer;
import com.threerings.crowd.server.PlaceManager;
import com.threerings.whirled.Log;
-import com.threerings.whirled.data.Scene;
+import com.threerings.whirled.data.SceneModel;
import com.threerings.whirled.data.SceneObject;
import com.threerings.whirled.server.persist.SceneRepository;
@@ -43,9 +43,18 @@ public class SceneRegistry
{
_screp = screp;
- // we'll use this to do database stuff
- _invoker = new Invoker();
- _invoker.start();
+ // use a default runtime scene factory for now; assume that
+ // containing systems will call setRuntimeSceneFactory() later
+ _scfact = new DefaultRuntimeSceneFactory();
+ }
+
+ /**
+ * Instructs the scene registry to use the supplied factory to create
+ * runtime scene instances from scene models.
+ */
+ public void setRuntimeSceneFactory (RuntimeSceneFactory factory)
+ {
+ _scfact = factory;
}
/**
@@ -120,24 +129,23 @@ public class SceneRegistry
} else {
// otherwise we've got to initiate the resolution process.
// first we create the penders list
- penders = new ArrayList();
- _penders.put(sceneId, penders);
+ _penders.put(sceneId, penders = new ArrayList());
penders.add(target);
// i don't like cluttering up method declarations with final
// keywords...
final int fsceneId = sceneId;
- Log.info("Invoking scene repository [id=" + sceneId + "].");
+ Log.info("Invoking scene lookup [id=" + sceneId + "].");
// then we queue up an execution unit that'll load the scene
// and initialize it and all that
- _invoker.postUnit(new Invoker.Unit() {
+ WhirledServer.invoker.postUnit(new Invoker.Unit() {
// this is run on the invoker thread
public boolean invoke ()
{
try {
- _scene = _screp.loadScene(fsceneId);
+ _model = _screp.loadSceneModel(fsceneId);
} catch (Exception e) {
_cause = e;
}
@@ -147,8 +155,8 @@ public class SceneRegistry
// this is run on the dobjmgr thread
public void handleResult ()
{
- if (_scene != null) {
- processSuccessfulResolution(_scene);
+ if (_model != null) {
+ processSuccessfulResolution(_model);
} else if (_cause != null) {
processFailedResolution(fsceneId, _cause);
} else {
@@ -158,7 +166,7 @@ public class SceneRegistry
}
}
- protected Scene _scene;
+ protected SceneModel _model;
protected Exception _cause;
});
}
@@ -167,7 +175,7 @@ public class SceneRegistry
/**
* Called when the scene resolution has completed successfully.
*/
- protected void processSuccessfulResolution (Scene scene)
+ protected void processSuccessfulResolution (SceneModel model)
{
// now that the scene is loaded, we can create a scene manager for
// it. that will be initialized by the place registry and when
@@ -175,6 +183,10 @@ public class SceneRegistry
// what's up
try {
+ // first create our runtime scene instance
+ RuntimeScene scene = _scfact.createScene(model);
+
+ // now create our scene manager
SceneManager scmgr = (SceneManager)
CrowdServer.plreg.createPlace(scene.getPlaceConfig(), null);
@@ -182,7 +194,7 @@ public class SceneRegistry
// stuff; we'll somehow need to convey configuration
// information for the scene to the scene manager, but for now
// let's punt
- scmgr.postInit(scene, this);
+ scmgr.postInit(scene, model, this);
// when the scene manager completes its startup procedings, it
// will call back to the scene registry and let us know that
@@ -190,7 +202,7 @@ public class SceneRegistry
} catch (InstantiationException ie) {
// so close, but no cigar
- processFailedResolution(scene.getId(), ie);
+ processFailedResolution(model.sceneId, ie);
}
}
@@ -255,9 +267,16 @@ public class SceneRegistry
}
}
+ /** The entity from which we load scene models. */
protected SceneRepository _screp;
- protected Invoker _invoker;
-
+
+ /** The entity via which we create runtime scene instances from scene
+ * models. */
+ protected RuntimeSceneFactory _scfact;
+
+ /** A mapping from scene ids to scene managers. */
protected HashIntMap _scenemgrs = new HashIntMap();
+
+ /** The table of pending resolution listeners. */
protected HashIntMap _penders = new HashIntMap();
}
diff --git a/src/java/com/threerings/whirled/server/WhirledServer.java b/src/java/com/threerings/whirled/server/WhirledServer.java
index c9f9ffab5..f2c82c3f8 100644
--- a/src/java/com/threerings/whirled/server/WhirledServer.java
+++ b/src/java/com/threerings/whirled/server/WhirledServer.java
@@ -1,5 +1,5 @@
//
-// $Id: WhirledServer.java,v 1.8 2001/11/08 02:59:17 mdb Exp $
+// $Id: WhirledServer.java,v 1.9 2001/11/12 20:56:56 mdb Exp $
package com.threerings.whirled.server;
@@ -7,6 +7,7 @@ import com.samskivert.jdbc.ConnectionProvider;
import com.samskivert.jdbc.StaticConnectionProvider;
import com.samskivert.util.Config;
+import com.threerings.presents.util.Invoker;
import com.threerings.crowd.server.CrowdServer;
import com.threerings.whirled.Log;
@@ -28,6 +29,9 @@ public class WhirledServer extends CrowdServer
/** The scene registry. */
public static SceneRegistry screg;
+ /** A thread on which we can do things like repository lookups. */
+ public static Invoker invoker;
+
/**
* Initializes all of the server services and prepares for operation.
*/
@@ -40,6 +44,10 @@ public class WhirledServer extends CrowdServer
// bind the whirled server config into the namespace
config.bindProperties(CONFIG_KEY, CONFIG_PATH, true);
+ // create and start up our invoker
+ invoker = new Invoker();
+ invoker.start();
+
// create our connection provider
conprov = createConnectionProvider(config);
diff --git a/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java b/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java
index b8cd21195..da2f26378 100644
--- a/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java
+++ b/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java
@@ -1,13 +1,12 @@
//
-// $Id: DummySceneRepository.java,v 1.6 2001/11/08 02:59:17 mdb Exp $
+// $Id: DummySceneRepository.java,v 1.7 2001/11/12 20:56:56 mdb Exp $
package com.threerings.whirled.server.persist;
import com.samskivert.io.PersistenceException;
import com.threerings.whirled.Log;
-import com.threerings.whirled.data.DummyScene;
-import com.threerings.whirled.data.Scene;
+import com.threerings.whirled.data.SceneModel;
import com.threerings.whirled.util.NoSuchSceneException;
/**
@@ -18,15 +17,22 @@ import com.threerings.whirled.util.NoSuchSceneException;
public class DummySceneRepository implements SceneRepository
{
// documentation inherited
- public Scene loadScene (int sceneId)
+ public SceneModel loadSceneModel (int sceneId)
throws PersistenceException, NoSuchSceneException
{
Log.info("Creating dummy scene [id=" + sceneId + "].");
- return new DummyScene(sceneId);
+
+ // create a blank scene model
+ SceneModel model = new SceneModel();
+ model.sceneId = sceneId;
+ model.version = 1;
+ model.neighborIds = new int[0];
+
+ return model;
}
// documentation inherited
- public void updateScene (Scene scene)
+ public void updateSceneModel (SceneModel model)
throws PersistenceException
{
// nothing doing
diff --git a/src/java/com/threerings/whirled/server/persist/SceneRepository.java b/src/java/com/threerings/whirled/server/persist/SceneRepository.java
index 75f63086e..c206ee515 100644
--- a/src/java/com/threerings/whirled/server/persist/SceneRepository.java
+++ b/src/java/com/threerings/whirled/server/persist/SceneRepository.java
@@ -1,40 +1,39 @@
//
-// $Id: SceneRepository.java,v 1.4 2001/09/28 22:15:57 mdb Exp $
+// $Id: SceneRepository.java,v 1.5 2001/11/12 20:56:56 mdb Exp $
package com.threerings.whirled.server.persist;
import com.samskivert.io.PersistenceException;
-import com.threerings.whirled.data.Scene;
+import com.threerings.whirled.data.SceneModel;
import com.threerings.whirled.util.NoSuchSceneException;
/**
* The scene repository provides the basic interface for loading and
- * updating scenes. It is used by the scene registry and though more scene
- * related persistence services may be needed in a full-fledged
+ * updating scene data. It is used by the scene registry and though more
+ * scene related persistence services may be needed in a full-fledged
* application, the scene repository only encapsulates those needed by the
* scene registry and other services provided by the Whirled framework.
*/
public interface SceneRepository
{
/**
- * Fetches the scene with the specified scene id.
+ * Fetches the model for the scene with the specified scene id.
*
* @exception PersistenceException thrown if an error occurs
- * attempting to load a scene.
+ * attempting to load the scene data.
* @exception NoSuchSceneException thrown if no scene exists with the
* specified scene id.
*/
- public Scene loadScene (int sceneId)
+ public SceneModel loadSceneModel (int sceneId)
throws PersistenceException, NoSuchSceneException;
/**
- * Updates the specified scene in the repository with the information
- * provided in the scene object.
+ * Updates the specified scene model in the repository.
*
* @exception PersistenceException thrown if an error occurs
- * attempting to update the scene.
+ * attempting to update the scene data.
*/
- public void updateScene (Scene scene)
+ public void updateSceneModel (SceneModel scene)
throws PersistenceException;
}
diff --git a/src/java/com/threerings/whirled/tools/EditableScene.java b/src/java/com/threerings/whirled/tools/EditableScene.java
new file mode 100644
index 000000000..5da295e7a
--- /dev/null
+++ b/src/java/com/threerings/whirled/tools/EditableScene.java
@@ -0,0 +1,51 @@
+//
+// $Id: EditableScene.java,v 1.1 2001/11/12 20:56:56 mdb Exp $
+
+package com.threerings.whirled.tools;
+
+import com.threerings.whirled.client.DisplayScene;
+import com.threerings.whirled.data.SceneModel;
+
+/**
+ * The editable scene interface is used in the offline scene building
+ * tools as well as by the tools that load those prototype scenes into the
+ * runtime database. Accordingly, it provides a means for modifying scene
+ * values and for obtaining access to the underlying scene models that
+ * represent the underlying scene information.
+ *
+ *
Because the editable scene is used in the scene editor, where it is + * displayed, the editable scene interface extends the {@link + * DisplayScene} interface so that the same display mechanisms can be used + * in the client and the editor. This leaves one anomaly, however which is + * that {@link #getPlaceConfig} is out of place in the editor or in + * loading tools. Instead of complicating things with an additional + * interface that factors out that method, we instead recommend that + * editable scene implementations simply return null from that method with + * the expectation that it will never be called. + */ +public interface EditableScene extends DisplayScene +{ + /** + * Sets this scene's unique identifier. + */ + public void setId (int sceneId); + + /** + * Sets this scene's version number. + */ + public void setVersion (int version); + + /** + * Sets the ids of the neighbors of this scene. + */ + public void setNeighborIds (int[] neighborIds); + + /** + * Implementations must provide a scene model that represents the + * current state of this editable scene in response to a call to this + * method. Whether they maintain an up to date scene model all along + * or generate one at the time this method is called is up to the + * implementation. + */ + public SceneModel getSceneModel (); +} diff --git a/src/java/com/threerings/whirled/tools/EditableSceneImpl.java b/src/java/com/threerings/whirled/tools/EditableSceneImpl.java new file mode 100644 index 000000000..2e94994bc --- /dev/null +++ b/src/java/com/threerings/whirled/tools/EditableSceneImpl.java @@ -0,0 +1,49 @@ +// +// $Id: EditableSceneImpl.java,v 1.1 2001/11/12 20:56:56 mdb Exp $ + +package com.threerings.whirled.tools; + +import com.threerings.crowd.data.PlaceConfig; +import com.threerings.whirled.client.DisplaySceneImpl; +import com.threerings.whirled.data.SceneModel; + +/** + * A basic implementation of the {@link EditableScene} interface. + */ +public class EditableSceneImpl + extends DisplaySceneImpl + implements EditableScene +{ + /** + * Creates an instance that will obtain data from the supplied scene + * model and update it when changes are made. + */ + public EditableSceneImpl (SceneModel model) + { + super(model, null); + } + + // documentation inherited + public void setId (int sceneId) + { + _model.sceneId = sceneId; + } + + // documentation inherited + public void setVersion (int version) + { + _model.version = version; + } + + // documentation inherited + public void setNeighborIds (int[] neighborIds) + { + _model.neighborIds = neighborIds; + } + + // documentation inherited + public SceneModel getSceneModel () + { + return _model; + } +}