diff --git a/src/java/com/threerings/whirled/client/DefaultDisplaySceneFactory.java b/src/java/com/threerings/whirled/client/DefaultDisplaySceneFactory.java deleted file mode 100644 index 478754687..000000000 --- a/src/java/com/threerings/whirled/client/DefaultDisplaySceneFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -// -// $Id: DefaultDisplaySceneFactory.java,v 1.1 2001/11/18 04:09:23 mdb Exp $ - -package com.threerings.whirled.client; - -import com.threerings.crowd.data.PlaceConfig; -import com.threerings.whirled.data.SceneModel; - -/** - * The default display scene factory creates {@link DisplaySceneImpl} - * instances. - */ -public class DefaultDisplaySceneFactory implements DisplaySceneFactory -{ - // documentation inherited - public DisplayScene createScene (SceneModel model, PlaceConfig config) - { - return new DisplaySceneImpl(model, config); - } -} diff --git a/src/java/com/threerings/whirled/client/DisplayScene.java b/src/java/com/threerings/whirled/client/DisplayScene.java deleted file mode 100644 index db46fc0b0..000000000 --- a/src/java/com/threerings/whirled/client/DisplayScene.java +++ /dev/null @@ -1,50 +0,0 @@ -// -// $Id: DisplayScene.java,v 1.2 2001/12/12 19:06:15 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 name of this scene.
- */
- public String getName ();
-
- /**
- * 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
deleted file mode 100644
index 9ee977c3f..000000000
--- a/src/java/com/threerings/whirled/client/DisplaySceneFactory.java
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// $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
deleted file mode 100644
index df288b7f8..000000000
--- a/src/java/com/threerings/whirled/client/DisplaySceneImpl.java
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// $Id: DisplaySceneImpl.java,v 1.2 2001/12/12 19:06:15 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 String getName ()
- {
- return _model.sceneName;
- }
-
- // 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/SceneDirector.java b/src/java/com/threerings/whirled/client/SceneDirector.java
index 9c04ba6a4..182d7ea32 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.23 2002/12/09 04:44:33 shaper Exp $
+// $Id: SceneDirector.java,v 1.24 2003/02/12 07:23:30 mdb Exp $
package com.threerings.whirled.client;
@@ -19,10 +19,13 @@ import com.threerings.crowd.data.PlaceObject;
import com.threerings.whirled.Log;
import com.threerings.whirled.client.persist.SceneRepository;
+import com.threerings.whirled.data.Scene;
import com.threerings.whirled.data.SceneCodes;
import com.threerings.whirled.data.SceneModel;
import com.threerings.whirled.util.NoSuchSceneException;
+import com.threerings.whirled.util.SceneFactory;
import com.threerings.whirled.util.WhirledContext;
+import com.threerings.whirled.data.SceneUpdate;
/**
* The scene director is the client's interface to all things scene
@@ -49,10 +52,10 @@ public class SceneDirector extends BasicDirector
* @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.
+ * Scene} to create for the current system.
*/
public SceneDirector (WhirledContext ctx, LocationDirector locdir,
- SceneRepository screp, DisplaySceneFactory dsfact)
+ SceneRepository screp, SceneFactory fact)
{
super(ctx);
@@ -60,7 +63,7 @@ public class SceneDirector extends BasicDirector
_ctx = ctx;
_locdir = locdir;
_screp = screp;
- _dsfact = dsfact;
+ _fact = fact;
// set ourselves up as a failure handler with the location
// director because we need to do special processing
@@ -75,7 +78,7 @@ public class SceneDirector extends BasicDirector
* Returns the display scene object associated with the scene we
* currently occupy or null if we currently occupy no scene.
*/
- public DisplayScene getScene ()
+ public Scene getScene ()
{
return _scene;
}
@@ -202,25 +205,84 @@ public class SceneDirector extends BasicDirector
if (_model == null) {
Log.warning("Aiya! Unable to load scene [sid=" + _sceneId +
", plid=" + placeId + "].");
+ return;
}
// and finally create a display scene instance with the model and
// the place config
- _scene = _dsfact.createScene(_model, config);
+ _scene = _fact.createScene(_model, config);
}
// documentation inherited from interface
- public void moveSucceededPlusUpdate (
+ public void moveSucceededWithUpdates (
+ int placeId, PlaceConfig config, SceneUpdate[] updates)
+ {
+ // apply the updates to our cached scene
+ SceneModel model = loadSceneModel(_pendingSceneId);
+ boolean failure = false;
+ for (int ii = 0; ii < updates.length; ii++) {
+ try {
+ updates[ii].validate(model);
+ } catch (IllegalStateException ise) {
+ Log.warning("Scene update failed validation [model=" + model +
+ ", update=" + updates[ii] +
+ ", error=" + ise.getMessage() + "].");
+ failure = true;
+ break;
+ }
+
+ try {
+ updates[ii].apply(model);
+ } catch (Exception e) {
+ Log.warning("Failure applying scene update [model=" + model +
+ ", update=" + updates[ii] + "].");
+ Log.logStackTrace(e);
+ failure = true;
+ break;
+ }
+ }
+
+ if (failure) {
+ // delete the now half-booched scene model from the repository
+ try {
+ _screp.deleteSceneModel(_pendingSceneId);
+ } catch (IOException ioe) {
+ Log.warning("Failure removing booched scene model " +
+ "[sceneId=" + _pendingSceneId + "].");
+ Log.logStackTrace(ioe);
+ }
+
+ // act as if the scene move failed, though we'll be in a funny
+ // state because the server thinks we've changed scenes, but
+ // the client can try again without its booched scene model
+ requestFailed(INTERNAL_ERROR);
+ return;
+ }
+
+ // store the updated scene in the repository
+ try {
+ _screp.storeSceneModel(model);
+ } catch (IOException ioe) {
+ Log.warning("Failed to update repository with updated scene " +
+ "[sceneId=" + model.sceneId + "].");
+ Log.logStackTrace(ioe);
+ }
+
+ // finally pass through to the normal success handler
+ moveSucceeded(placeId, config);
+ }
+
+ // documentation inherited from interface
+ public void moveSucceededWithScene (
int placeId, PlaceConfig config, SceneModel model)
{
// update the model in the repository
try {
- _screp.updateSceneModel(model);
+ _screp.storeSceneModel(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.warning("Failed to update repository with new version " +
+ "[sceneId=" + model.sceneId +
+ ", nvers=" + model.version + "].");
Log.logStackTrace(ioe);
}
@@ -376,14 +438,14 @@ public class SceneDirector extends BasicDirector
/** 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;
+ /** The entity we use to create scenes from scene models. */
+ protected SceneFactory _fact;
/** A cache of scene model information. */
protected HashIntMap _scache = new HashIntMap();
/** The display scene object for the scene we currently occupy. */
- protected DisplayScene _scene;
+ protected Scene _scene;
/** The scene model for the scene we currently occupy. */
protected SceneModel _model;
diff --git a/src/java/com/threerings/whirled/client/SceneService.java b/src/java/com/threerings/whirled/client/SceneService.java
index d3095c7ae..a57596cbb 100644
--- a/src/java/com/threerings/whirled/client/SceneService.java
+++ b/src/java/com/threerings/whirled/client/SceneService.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneService.java,v 1.9 2002/08/14 19:07:57 mdb Exp $
+// $Id: SceneService.java,v 1.10 2003/02/12 07:23:30 mdb Exp $
package com.threerings.whirled.client;
@@ -7,7 +7,9 @@ import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
import com.threerings.crowd.data.PlaceConfig;
+
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
/**
* The scene service class provides the client interface to the scene
@@ -34,11 +36,23 @@ public interface SceneService extends InvocationService
*
* @param placeId the place object id of the newly occupied scene.
* @param config metadata related to the newly occupied scene.
- * @param model the most recent scene data for the newly occupied
- * scene.
+ * @param updates updates that must be applied to the client's
+ * copy of a scene model to bring it up to date.
*/
- public void moveSucceededPlusUpdate (
- int placeId, PlaceConfig config, SceneModel model);
+ public void moveSucceededWithUpdates (int placeId, PlaceConfig config,
+ SceneUpdate[] updates);
+
+ /**
+ * Indicates that a move succeeded and that the client's cached
+ * scene information should be updated with the supplied data.
+ *
+ * @param placeId the place object id of the newly occupied scene.
+ * @param config metadata related to the newly occupied scene.
+ * @param model a fresh copy of the most recent scene data for the
+ * newly occupied scene.
+ */
+ public void moveSucceededWithScene (int placeId, PlaceConfig config,
+ SceneModel model);
}
/**
@@ -46,9 +60,9 @@ public interface SceneService extends InvocationService
* scene.
*
* @param sceneId the scene id to which we want to move.
- * @param sceneVers the version number of the scene object that we
- * have in our local repository.
+ * @param version the version number of the scene object that we have
+ * in our local repository.
*/
- public void moveTo (Client client, int sceneId,
- int sceneVers, SceneMoveListener listener);
+ public void moveTo (Client client, int sceneId, int version,
+ SceneMoveListener listener);
}
diff --git a/src/java/com/threerings/whirled/client/persist/SceneRepository.java b/src/java/com/threerings/whirled/client/persist/SceneRepository.java
index 708879ab0..b8f916561 100644
--- a/src/java/com/threerings/whirled/client/persist/SceneRepository.java
+++ b/src/java/com/threerings/whirled/client/persist/SceneRepository.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneRepository.java,v 1.3 2001/11/12 20:56:55 mdb Exp $
+// $Id: SceneRepository.java,v 1.4 2003/02/12 07:23:30 mdb Exp $
package com.threerings.whirled.client.persist;
@@ -10,17 +10,14 @@ import com.threerings.whirled.util.NoSuchSceneException;
/**
* The scene repository provides access to a persistent repository of
- * 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.
+ * scene information.
*
* @see SceneModel
*/
public interface SceneRepository
{
/**
- * Fetches the mode for the scene with the specified scene id.
+ * Fetches the model for the scene with the specified id.
*
* @exception IOException thrown if an error occurs attempting to load
* the scene data.
@@ -31,13 +28,20 @@ public interface SceneRepository
throws IOException, NoSuchSceneException;
/**
- * 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.
+ * Updates or inserts this scene model as appropriate.
*
* @exception IOException thrown if an error occurs attempting to
- * update the scene data.
+ * access the repository.
*/
- public void updateSceneModel (SceneModel model)
+ public void storeSceneModel (SceneModel model)
+ throws IOException;
+
+ /**
+ * Deletes the specified scene model from the repository.
+ *
+ * @exception IOException thrown if an error occurs attempting to
+ * access the repository.
+ */
+ public void deleteSceneModel (int sceneId)
throws IOException;
}
diff --git a/src/java/com/threerings/whirled/data/AuxModel.java b/src/java/com/threerings/whirled/data/AuxModel.java
new file mode 100644
index 000000000..464454133
--- /dev/null
+++ b/src/java/com/threerings/whirled/data/AuxModel.java
@@ -0,0 +1,18 @@
+//
+// $Id: AuxModel.java,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.data;
+
+import com.threerings.io.Streamable;
+
+/**
+ * An interface that must be implemented by auxiliary scene models.
+ */
+public interface AuxModel extends Streamable, Cloneable
+{
+ /**
+ * Creates a clone of this auxiliary model.
+ */
+ public Object clone ()
+ throws CloneNotSupportedException;
+}
diff --git a/src/java/com/threerings/whirled/data/Scene.java b/src/java/com/threerings/whirled/data/Scene.java
new file mode 100644
index 000000000..fb89834df
--- /dev/null
+++ b/src/java/com/threerings/whirled/data/Scene.java
@@ -0,0 +1,57 @@
+//
+// $Id: Scene.java,v 1.8 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.data;
+
+import com.threerings.crowd.data.PlaceConfig;
+
+/**
+ * This interface makes available basic scene information. 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.
+ */
+public interface Scene
+{
+ /**
+ * Returns the unique identifier for this scene.
+ */
+ public int getId ();
+
+ /**
+ * Returns the human readable name of this scene.
+ */
+ public String getName ();
+
+ /**
+ * Returns the version number of this scene.
+ */
+ public int getVersion ();
+
+ /**
+ * 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 ();
+
+ /**
+ * Sets this scene's unique identifier.
+ */
+ public void setId (int sceneId);
+
+ /**
+ * Sets the human readable name of this scene.
+ */
+ public void setName (String name);
+
+ /**
+ * Sets this scene's version number.
+ */
+ public void setVersion (int version);
+
+ /**
+ * Returns the scene model from which this scene was created.
+ */
+ public SceneModel getSceneModel ();
+}
diff --git a/src/java/com/threerings/whirled/data/SceneImpl.java b/src/java/com/threerings/whirled/data/SceneImpl.java
new file mode 100644
index 000000000..22f7b1702
--- /dev/null
+++ b/src/java/com/threerings/whirled/data/SceneImpl.java
@@ -0,0 +1,94 @@
+//
+// $Id: SceneImpl.java,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.data;
+
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.whirled.data.SceneModel;
+
+/**
+ * An implementation of the {@link Scene} interface.
+ */
+public class SceneImpl implements Scene
+{
+ /**
+ * Creates an instance that will obtain data from the supplied scene
+ * model and place config.
+ */
+ public SceneImpl (SceneModel model, PlaceConfig config)
+ {
+ _model = model;
+ _config = config;
+ }
+
+ /**
+ * Instantiates a blank scene implementation. No place config will be
+ * associated with this scene.
+ */
+ public SceneImpl ()
+ {
+ _model = SceneModel.blankSceneModel();
+ }
+
+ // documentation inherited
+ public int getId ()
+ {
+ return _model.sceneId;
+ }
+
+ // documentation inherited
+ public String getName ()
+ {
+ return _model.name;
+ }
+
+ // documentation inherited
+ public int getVersion ()
+ {
+ return _model.version;
+ }
+
+ // documentation inherited
+ public PlaceConfig getPlaceConfig ()
+ {
+ return _config;
+ }
+
+ // documentation inherited from interface
+ public void setId (int sceneId)
+ {
+ _model.sceneId = sceneId;
+ }
+
+ // documentation inherited from interface
+ public void setName (String name)
+ {
+ _model.name = name;
+ }
+
+ // documentation inherited from interface
+ public void setVersion (int version)
+ {
+ _model.version = version;
+ }
+
+ // documentation inherited from interface
+ public SceneModel getSceneModel ()
+ {
+ return _model;
+ }
+
+ /**
+ * Generates a string representation of this instance.
+ */
+ public String toString ()
+ {
+ return "[model=" + _model + ", config=" + _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/data/SceneMarshaller.java b/src/java/com/threerings/whirled/data/SceneMarshaller.java
index c5b9ec89c..782173ded 100644
--- a/src/java/com/threerings/whirled/data/SceneMarshaller.java
+++ b/src/java/com/threerings/whirled/data/SceneMarshaller.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneMarshaller.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
+// $Id: SceneMarshaller.java,v 1.3 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.data;
@@ -10,6 +10,7 @@ import com.threerings.presents.dobj.InvocationResponseEvent;
import com.threerings.whirled.client.SceneService;
import com.threerings.whirled.client.SceneService.SceneMoveListener;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
/**
* Provides the implementation of the {@link SceneService} interface
@@ -17,10 +18,6 @@ import com.threerings.whirled.data.SceneModel;
* on the server. Also provides an implementation of the response listener
* interfaces that marshall the response arguments and deliver them back
* to the requesting client.
- *
- *
Generated from
- * $Id: SceneMarshaller.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
- *
*/
public class SceneMarshaller extends InvocationMarshaller
implements SceneService
@@ -41,15 +38,27 @@ public class SceneMarshaller extends InvocationMarshaller
new Object[] { new Integer(arg1), arg2 }));
}
- /** The method id used to dispatch {@link #moveSucceededPlusUpdate}
+ /** The method id used to dispatch {@link #moveSucceededWithUpdates}
* responses. */
- public static final int MOVE_SUCCEEDED_PLUS_UPDATE = 2;
+ public static final int MOVE_SUCCEEDED_WITH_UPDATES = 2;
// documentation inherited from interface
- public void moveSucceededPlusUpdate (int arg1, PlaceConfig arg2, SceneModel arg3)
+ public void moveSucceededWithUpdates (int arg1, PlaceConfig arg2, SceneUpdate[] arg3)
{
omgr.postEvent(new InvocationResponseEvent(
- callerOid, requestId, MOVE_SUCCEEDED_PLUS_UPDATE,
+ callerOid, requestId, MOVE_SUCCEEDED_WITH_UPDATES,
+ new Object[] { new Integer(arg1), arg2, arg3 }));
+ }
+
+ /** The method id used to dispatch {@link #moveSucceededWithScene}
+ * responses. */
+ public static final int MOVE_SUCCEEDED_WITH_SCENE = 3;
+
+ // documentation inherited from interface
+ public void moveSucceededWithScene (int arg1, PlaceConfig arg2, SceneModel arg3)
+ {
+ omgr.postEvent(new InvocationResponseEvent(
+ callerOid, requestId, MOVE_SUCCEEDED_WITH_SCENE,
new Object[] { new Integer(arg1), arg2, arg3 }));
}
@@ -62,8 +71,13 @@ public class SceneMarshaller extends InvocationMarshaller
((Integer)args[0]).intValue(), (PlaceConfig)args[1]);
return;
- case MOVE_SUCCEEDED_PLUS_UPDATE:
- ((SceneMoveListener)listener).moveSucceededPlusUpdate(
+ case MOVE_SUCCEEDED_WITH_UPDATES:
+ ((SceneMoveListener)listener).moveSucceededWithUpdates(
+ ((Integer)args[0]).intValue(), (PlaceConfig)args[1], (SceneUpdate[])args[2]);
+ return;
+
+ case MOVE_SUCCEEDED_WITH_SCENE:
+ ((SceneMoveListener)listener).moveSucceededWithScene(
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (SceneModel)args[2]);
return;
@@ -86,5 +100,5 @@ public class SceneMarshaller extends InvocationMarshaller
});
}
- // Class file generated on 12:33:06 08/20/02.
+ // Generated on 14:44:07 02/08/03.
}
diff --git a/src/java/com/threerings/whirled/data/SceneModel.java b/src/java/com/threerings/whirled/data/SceneModel.java
index 41add44cc..f07b360af 100644
--- a/src/java/com/threerings/whirled/data/SceneModel.java
+++ b/src/java/com/threerings/whirled/data/SceneModel.java
@@ -1,18 +1,16 @@
//
-// $Id: SceneModel.java,v 1.8 2002/07/23 05:54:52 mdb Exp $
+// $Id: SceneModel.java,v 1.9 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.data;
-import com.samskivert.util.StringUtil;
+import com.samskivert.util.ArrayUtil;
import com.threerings.io.SimpleStreamableObject;
/**
* 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}.
+ * instance of {@link Scene}.
*
*
The scene model is what is loaded from the scene repositories and
* what is transmitted over the wire when communicating scenes from the
@@ -25,7 +23,7 @@ public class SceneModel extends SimpleStreamableObject
public int sceneId;
/** The human readable name of this scene. */
- public String sceneName;
+ public String name;
/** The version number of this scene. Versions are incremented
* whenever modifications are made to a scene so that clients can
@@ -33,18 +31,15 @@ public class SceneModel extends SimpleStreamableObject
* 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;
+ /** Auxiliary scene model information. */
+ public AuxModel[] auxModels = new AuxModel[0];
/**
- * Generates a string representation of this scene model.
+ * Adds the specified auxiliary model to this scene model.
*/
- public String toString ()
+ public void addAuxModel (AuxModel auxModel)
{
- StringBuffer buf = new StringBuffer("[");
- toString(buf);
- return buf.append("]").toString();
+ auxModels = (AuxModel[])ArrayUtil.append(auxModels, auxModel);
}
// documentation inherited
@@ -52,22 +47,13 @@ public class SceneModel extends SimpleStreamableObject
throws CloneNotSupportedException
{
SceneModel model = (SceneModel)super.clone();
- model.neighborIds = (int[])neighborIds.clone();
+ model.auxModels = new AuxModel[auxModels.length];
+ for (int ii = 0; ii < auxModels.length; ii++) {
+ model.auxModels[ii] = (AuxModel)auxModels[ii].clone();
+ }
return model;
}
- /**
- * Derived classes override this to tack their Additionally, at this basic level, the Generated from The scene repository also takes care of bridging from the blocking,
* synchronous world of the scene repository to the non-blocking
@@ -37,6 +41,18 @@ import com.threerings.whirled.server.persist.SceneRepository;
*/
public class SceneRegistry
{
+ /**
+ * Used to create {@link PlaceConfig} instances for scenes.
+ */
+ public static interface ConfigFactory
+ {
+ /**
+ * Creates the place config instance appropriate to the specified
+ * scene.
+ */
+ PlaceConfig createPlaceConfig (SceneModel model);
+ }
+
/** Used to provide scene-related server-side services. */
public SceneProvider sceneprov;
@@ -44,28 +60,18 @@ public class SceneRegistry
* Constructs a scene registry, instructing it to load and store
* scenes using the supplied scene repository.
*/
- public SceneRegistry (InvocationManager invmgr, SceneRepository screp)
+ public SceneRegistry (InvocationManager invmgr, SceneRepository screp,
+ SceneFactory scfact, ConfigFactory confact)
{
_screp = screp;
-
- // use a default runtime scene factory for now; assume that
- // containing systems will call setRuntimeSceneFactory() later
- _scfact = new DefaultRuntimeSceneFactory();
+ _scfact = scfact;
+ _confact = confact;
// create/register a scene provider with the invocation services
sceneprov = new SceneProvider(CrowdServer.plreg.locprov, this);
invmgr.registerDispatcher(new SceneDispatcher(sceneprov), true);
}
- /**
- * Instructs the scene registry to use the supplied factory to create
- * runtime scene instances from scene models.
- */
- public void setRuntimeSceneFactory (RuntimeSceneFactory factory)
- {
- _scfact = factory;
- }
-
/**
* Fetches the scene manager assosciated with the specified scene.
*
@@ -77,6 +83,15 @@ public class SceneRegistry
return (SceneManager)_scenemgrs.get(sceneId);
}
+ /**
+ * Returns a reference to the scene repository in use by this
+ * registry.
+ */
+ public SceneRepository getSceneRepository ()
+ {
+ return _screp;
+ }
+
/**
* Because scenes must be loaded from the scene repository and this
* must not be done on the dobjmgr thread, the interface for resolving
@@ -155,6 +170,7 @@ public class SceneRegistry
{
try {
_model = _screp.loadSceneModel(fsceneId);
+ _updates = _screp.loadUpdates(fsceneId);
} catch (Exception e) {
_cause = e;
}
@@ -165,7 +181,7 @@ public class SceneRegistry
public void handleResult ()
{
if (_model != null) {
- processSuccessfulResolution(_model);
+ processSuccessfulResolution(_model, _updates);
} else if (_cause != null) {
processFailedResolution(fsceneId, _cause);
} else {
@@ -176,6 +192,7 @@ public class SceneRegistry
}
protected SceneModel _model;
+ protected UpdateList _updates;
protected Exception _cause;
});
}
@@ -184,7 +201,8 @@ public class SceneRegistry
/**
* Called when the scene resolution has completed successfully.
*/
- protected void processSuccessfulResolution (SceneModel model)
+ protected void processSuccessfulResolution (
+ SceneModel model, UpdateList updates)
{
// now that the scene is loaded, we can create a scene manager for
// it. that will be initialized by the place registry and when
@@ -192,18 +210,14 @@ public class SceneRegistry
// what's up
try {
- // first create our runtime scene instance
- RuntimeScene scene = _scfact.createScene(model);
+ // first create our scene instance
+ Scene scene = _scfact.createScene(
+ model, _confact.createPlaceConfig(model));
// now create our scene manager
SceneManager scmgr = (SceneManager)
CrowdServer.plreg.createPlace(scene.getPlaceConfig(), null);
-
- // configure the scene manager with references to useful
- // stuff; we'll somehow need to convey configuration
- // information for the scene to the scene manager, but for now
- // let's punt
- scmgr.setSceneData(scene, model, this);
+ scmgr.setSceneData(scene, updates, this);
// when the scene manager completes its startup procedings, it
// will call back to the scene registry and let us know that
@@ -282,9 +296,12 @@ public class SceneRegistry
/** The entity from which we load scene models. */
protected SceneRepository _screp;
- /** The entity via which we create runtime scene instances from scene
+ /** Used to generate place configs for our scenes. */
+ protected ConfigFactory _confact;
+
+ /** The entity via which we create scene instances from scene
* models. */
- protected RuntimeSceneFactory _scfact;
+ protected SceneFactory _scfact;
/** A mapping from scene ids to scene managers. */
protected HashIntMap _scenemgrs = new HashIntMap();
diff --git a/src/java/com/threerings/whirled/server/WhirledServer.java b/src/java/com/threerings/whirled/server/WhirledServer.java
index 77d9bff6e..dae03a074 100644
--- a/src/java/com/threerings/whirled/server/WhirledServer.java
+++ b/src/java/com/threerings/whirled/server/WhirledServer.java
@@ -1,19 +1,20 @@
//
-// $Id: WhirledServer.java,v 1.15 2002/10/21 20:56:21 mdb Exp $
+// $Id: WhirledServer.java,v 1.16 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.server;
import com.threerings.crowd.server.CrowdServer;
import com.threerings.whirled.Log;
-import com.threerings.whirled.server.persist.SceneRepository;
import com.threerings.whirled.server.persist.DummySceneRepository;
+import com.threerings.whirled.server.persist.SceneRepository;
+import com.threerings.whirled.util.SceneFactory;
/**
* The whirled server extends the {@link CrowdServer} and provides access
* to managers and the like that are needed by the Whirled serviecs.
*/
-public class WhirledServer extends CrowdServer
+public abstract class WhirledServer extends CrowdServer
{
/** The scene registry. */
public static SceneRegistry screg;
@@ -34,25 +35,39 @@ public class WhirledServer extends CrowdServer
_screp = createSceneRepository();
// create our scene registry
- screg = new SceneRegistry(invmgr, _screp);
+ screg = new SceneRegistry(invmgr, _screp, createSceneFactory(),
+ createConfigFactory());
Log.info("Whirled server initialized.");
}
/**
- * Creates the scene repository that will be used by this server. If a
- * derived class wishes to use a particular kind of scene repository
- * (which they most likely will), they should override this method and
- * instantiate the scene repository of their choosing.
+ * Creates the scene repository that will be used by this server.
*
* @exception Exception thrown if any error occurs while instantiating
* or initializing the scene repository.
*/
- protected SceneRepository createSceneRepository ()
- throws Exception
- {
- return new DummySceneRepository();
- }
+ protected abstract SceneRepository createSceneRepository ()
+ throws Exception;
+
+ /**
+ * Creates the scene factory that will be used by our scene registry.
+ *
+ * @exception Exception thrown if any error occurs while instantiating
+ * or initializing the scene repository.
+ */
+ protected abstract SceneFactory createSceneFactory ()
+ throws Exception;
+
+ /**
+ * Creates the place config factory that will be used our scene
+ * registry.
+ *
+ * @exception Exception thrown if any error occurs while instantiating
+ * or initializing the scene repository.
+ */
+ protected abstract SceneRegistry.ConfigFactory createConfigFactory ()
+ throws Exception;
/** The scene repository in use by this server. */
protected SceneRepository _screp;
diff --git a/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java b/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java
index da2f26378..ed004b2af 100644
--- a/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java
+++ b/src/java/com/threerings/whirled/server/persist/DummySceneRepository.java
@@ -1,5 +1,5 @@
//
-// $Id: DummySceneRepository.java,v 1.7 2001/11/12 20:56:56 mdb Exp $
+// $Id: DummySceneRepository.java,v 1.8 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.server.persist;
@@ -7,7 +7,9 @@ import com.samskivert.io.PersistenceException;
import com.threerings.whirled.Log;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
import com.threerings.whirled.util.NoSuchSceneException;
+import com.threerings.whirled.util.UpdateList;
/**
* The dummy scene repository just pretends to load and store scenes, but
@@ -21,18 +23,18 @@ public class DummySceneRepository implements SceneRepository
throws PersistenceException, NoSuchSceneException
{
Log.info("Creating dummy scene [id=" + sceneId + "].");
-
- // create a blank scene model
- SceneModel model = new SceneModel();
- model.sceneId = sceneId;
- model.version = 1;
- model.neighborIds = new int[0];
-
- return model;
+ return SceneModel.blankSceneModel();
}
- // documentation inherited
- public void updateSceneModel (SceneModel model)
+ // documentation inherited from interface
+ public UpdateList loadUpdates (int sceneId)
+ throws PersistenceException, NoSuchSceneException
+ {
+ return new UpdateList();
+ }
+
+ // documentation inherited from interface
+ public void addUpdate (SceneUpdate update)
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 c206ee515..ee2920ee4 100644
--- a/src/java/com/threerings/whirled/server/persist/SceneRepository.java
+++ b/src/java/com/threerings/whirled/server/persist/SceneRepository.java
@@ -1,12 +1,14 @@
//
-// $Id: SceneRepository.java,v 1.5 2001/11/12 20:56:56 mdb Exp $
+// $Id: SceneRepository.java,v 1.6 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.server.persist;
import com.samskivert.io.PersistenceException;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
import com.threerings.whirled.util.NoSuchSceneException;
+import com.threerings.whirled.util.UpdateList;
/**
* The scene repository provides the basic interface for loading and
@@ -29,11 +31,23 @@ public interface SceneRepository
throws PersistenceException, NoSuchSceneException;
/**
- * Updates the specified scene model in the repository.
+ * Fetches the set of updates associated with the specified scene.
*
* @exception PersistenceException thrown if an error occurs
- * attempting to update the scene data.
+ * attempting to load the scene updates.
+ * @exception NoSuchSceneException thrown if no scene exists with the
+ * specified scene id.
*/
- public void updateSceneModel (SceneModel scene)
+ public UpdateList loadUpdates (int sceneId)
+ throws PersistenceException, NoSuchSceneException;
+
+ /**
+ * Adds the supplied scene update to the list of updates for its
+ * associated scene.
+ *
+ * @exception PersistenceException thrown if an error occurs
+ * attempting to store the scene update.
+ */
+ public void addUpdate (SceneUpdate update)
throws PersistenceException;
}
diff --git a/src/java/com/threerings/whirled/spot/client/DisplaySpotScene.java b/src/java/com/threerings/whirled/spot/client/DisplaySpotScene.java
deleted file mode 100644
index 03aae15de..000000000
--- a/src/java/com/threerings/whirled/spot/client/DisplaySpotScene.java
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// $Id: DisplaySpotScene.java,v 1.4 2001/12/16 21:22:30 mdb Exp $
-
-package com.threerings.whirled.spot.client;
-
-import java.util.List;
-
-import com.threerings.whirled.client.DisplayScene;
-
-import com.threerings.whirled.spot.data.Location;
-import com.threerings.whirled.spot.data.Portal;
-
-/**
- * Makes available the spot scene information that the client needs to
- * display a spot scene, to make requests to the server to move from
- * location to location and to neighboring scenes and to display the same.
- */
-public interface DisplaySpotScene extends DisplayScene
-{
- /**
- * Returns the location id of the default entrance to this scene.
- */
- public int getDefaultEntranceId ();
-
- /**
- * Returns a list of the locations in this scene (including portals
- * which will be instances of {@link Portal}).
- */
- public List getLocations ();
-
- /**
- * Convenience function for obtaining a location's index in the
- * location list given its id.
- *
- * @return the location's index or -1 if a location with the specified
- * id is not in this scene's location list.
- */
- public int getLocationIndex (int locationId);
-
- /**
- * Convenience funtion for looking up a location by id.
- */
- public Location getLocation (int locationId);
-
- /**
- * Returns a list of the portals in this scene.
- */
- public List getPortals ();
-}
diff --git a/src/java/com/threerings/whirled/spot/client/DisplaySpotSceneImpl.java b/src/java/com/threerings/whirled/spot/client/DisplaySpotSceneImpl.java
deleted file mode 100644
index 992c333b6..000000000
--- a/src/java/com/threerings/whirled/spot/client/DisplaySpotSceneImpl.java
+++ /dev/null
@@ -1,155 +0,0 @@
-//
-// $Id: DisplaySpotSceneImpl.java,v 1.5 2001/12/16 21:22:30 mdb Exp $
-
-package com.threerings.whirled.spot.client;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.threerings.crowd.data.PlaceConfig;
-import com.threerings.whirled.client.DisplaySceneImpl;
-
-import com.threerings.whirled.spot.data.Location;
-import com.threerings.whirled.spot.data.Portal;
-import com.threerings.whirled.spot.data.SpotSceneModel;
-
-/**
- * A basic implementation of the {@link DisplaySpotScene} interface which
- * is used by default if no extended implementation is desired.
- */
-public class DisplaySpotSceneImpl extends DisplaySceneImpl
-{
- /**
- * Creates an instance that will obtain data from the supplied scene
- * model and place config.
- */
- public DisplaySpotSceneImpl (SpotSceneModel model, PlaceConfig config)
- {
- super(model, config);
-
- // keep a casted reference to our model around
- _model = model;
-
- // sort out our locations and portals
- int lcount = model.locationIds.length;
- int pcount = model.portalIds.length;
- _portals = new ArrayList(pcount);
- _locations = new ArrayList(lcount - pcount);
-
- // because the portals ids are in the same order as the location
- // ids, we can parse them in one pass
- int pidx = 0;
- for (int i = 0; i < lcount; i++) {
- Location loc;
- // stop checking for portals once we've parsed them all
- int pid = (pidx < pcount) ? model.portalIds[pidx] : -1;
-
- if (model.locationIds[i] == pid) {
- // add this portal to the portals array
- Portal port = new Portal();
- populatePortal(model, port, i, pidx);
- _portals.add(port);;
- loc = port;
- pidx++;
-
- } else {
- loc = new Location();
- populateLocation(model, loc, i);
- }
-
- // everything goes into the locations array
- _locations.add(loc);
- }
- }
-
- /**
- * Populates a location instance with the specified index, using
- * information from the model.
- *
- * @param model the scene model.
- * @param loc the location instance to populate.
- * @param lidx the location index in the model arrays.
- */
- protected void populateLocation (
- SpotSceneModel model, Location loc, int lidx)
- {
- loc.locationId = model.locationIds[lidx];
- loc.x = model.locationX[lidx];
- loc.y = model.locationY[lidx];
- loc.orientation = model.locationOrients[lidx];
- loc.clusterIndex = model.locationClusters[lidx];
- }
-
- /**
- * Populates a portal instance with the specified index, using
- * information from the model.
- *
- * @param model the scene model.
- * @param port the portal to populate.
- * @param lidx the location index in the model arrays.
- * @param pidx the portal index in the model arrays.
- */
- protected void populatePortal (
- SpotSceneModel model, Portal port, int lidx, int pidx)
- {
- // populate the location fields
- populateLocation(model, port, lidx);
-
- // populate the portal-specific fields
- port.targetSceneId = model.neighborIds[pidx];
- port.targetLocId = model.targetLocIds[pidx];
- }
-
- // documentation inherited
- public int getDefaultEntranceId ()
- {
- return _model.defaultEntranceId;
- }
-
- // documentation inherited
- public List getLocations ()
- {
- return _locations;
- }
-
- // documentation inherited
- public int getLocationIndex (int locationId)
- {
- int lsize = _locations.size();
- for (int i = 0; i < lsize; i++) {
- Location loc = (Location)_locations.get(i);
- if (loc.locationId == locationId) {
- return i;
- }
- }
- return -1;
- }
-
- // documentation inherited
- public Location getLocation (int locationId)
- {
- int lsize = _locations.size();
- for (int i = 0; i < lsize; i++) {
- Location loc = (Location)_locations.get(i);
- if (loc.locationId == locationId) {
- return loc;
- }
- }
- return null;
- }
-
- // documentation inherited
- public List getPortals ()
- {
- return _portals;
- }
-
- /** The data that makes up our scene. */
- protected SpotSceneModel _model;
-
- /** A list of the locations (and portals) in this scene. */
- protected ArrayList _locations;
-
- /** A list of just the portals in this scene. */
- protected ArrayList _portals;
-}
diff --git a/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java b/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java
index e24c07eea..811a738b9 100644
--- a/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java
+++ b/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java
@@ -1,5 +1,5 @@
//
-// $Id: SpotSceneDirector.java,v 1.20 2003/01/03 23:07:00 shaper Exp $
+// $Id: SpotSceneDirector.java,v 1.21 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.client;
@@ -9,6 +9,8 @@ import com.samskivert.util.StringUtil;
import com.threerings.presents.client.BasicDirector;
import com.threerings.presents.client.Client;
+import com.threerings.presents.dobj.AttributeChangeListener;
+import com.threerings.presents.dobj.AttributeChangedEvent;
import com.threerings.presents.dobj.DObject;
import com.threerings.presents.dobj.DObjectManager;
@@ -26,16 +28,19 @@ import com.threerings.whirled.data.SceneModel;
import com.threerings.whirled.util.WhirledContext;
import com.threerings.whirled.spot.Log;
+import com.threerings.whirled.spot.data.ClusteredBodyObject;
import com.threerings.whirled.spot.data.Location;
import com.threerings.whirled.spot.data.Portal;
import com.threerings.whirled.spot.data.SpotCodes;
+import com.threerings.whirled.spot.data.SpotScene;
/**
* Extends the standard scene director with facilities to move between
* locations within a scene.
*/
public class SpotSceneDirector extends BasicDirector
- implements SpotCodes, Subscriber, SpotService.ChangeLocListener
+ implements SpotCodes, Subscriber, SpotService.ChangeLocListener,
+ AttributeChangeListener
{
/**
* This is used to communicate back to the caller of {@link
@@ -46,13 +51,13 @@ public class SpotSceneDirector extends BasicDirector
/**
* Indicates that the requested location change succeeded.
*/
- public void locationChangeSucceeded (int locationId);
+ public void locationChangeSucceeded (Location loc);
/**
* Indicates that the requested location change failed and
* provides a reason code explaining the failure.
*/
- public void locationChangeFailed (int locationId, String reason);
+ public void locationChangeFailed (Location loc, String reason);
}
/**
@@ -113,7 +118,7 @@ public class SpotSceneDirector extends BasicDirector
public boolean traversePortal (int portalId, ResultListener rl)
{
// look up the destination scene and location
- DisplaySpotScene scene = (DisplaySpotScene)_scdir.getScene();
+ SpotScene scene = (SpotScene)_scdir.getScene();
if (scene == null) {
Log.warning("Requested to traverse portal when we have " +
"no scene [portalId=" + portalId + "].");
@@ -121,26 +126,16 @@ public class SpotSceneDirector extends BasicDirector
}
// find the portal they're talking about
- int targetSceneId = -1, targetLocId = -1;
- Iterator portals = scene.getPortals().iterator();
- while (portals.hasNext()) {
- Portal portal = (Portal)portals.next();
- if (portal.locationId == portalId) {
- targetSceneId = portal.targetSceneId;
- targetLocId = portal.targetLocId;
- }
- }
-
- // make sure we found the portal
- if (targetSceneId == -1) {
- portals = scene.getPortals().iterator();
+ Portal dest = scene.getPortal(portalId);
+ if (dest == null) {
Log.warning("Requested to traverse non-existent portal " +
- "[portalId=" + portalId +
- ", portals=" + StringUtil.toString(portals) + "].");
+ "[portalId=" + portalId + ", portals=" +
+ StringUtil.toString(scene.getPortals()) + "].");
+ return false;
}
// prepare to move to this scene (sets up pending data)
- if (!_scdir.prepareMoveTo(targetSceneId, rl)) {
+ if (!_scdir.prepareMoveTo(dest.targetSceneId, rl)) {
return false;
}
@@ -154,53 +149,52 @@ public class SpotSceneDirector extends BasicDirector
}
// issue a traversePortal request
- _sservice.traversePortal(
- _ctx.getClient(), scene.getId(), portalId, sceneVer, _scdir);
+ _sservice.traversePortal(_ctx.getClient(), portalId, sceneVer, _scdir);
return true;
}
/**
* Issues a request to change our location within the scene to the
- * location identified by the specified id. Most client entities find
- * out about location changes via changes to the occupant info data,
- * but the initiator of a location change request can be notified of
- * its success or failure, primarily so that it can act in
- * anticipation of a successful location change (like by starting a
- * sprite moving toward the new location), but backtrack if it finds
- * out that the location change failed.
+ * specified location. Depending on the value of Though portals extend locations, they generally would not occupy a
- * cluster (because that wouldn't make much sense) and as such should
- * always have a {@link #clusterIndex} of -1.
+ * Represents an exit to another scene. A body sprite would walk over to a
+ * portal's coordinates and then either proceed off of the edge of the
+ * display, or open a door and walk through it, or fizzle away in a Star
+ * Trekkian transporter style or whatever is appropriate for the game in
+ * question. It contains information on the scene to which the body exits
+ * when using this portal and the location at which the body sprite should
+ * appear in that target scene.
*/
-public class Portal extends Location
+public class Portal extends SimpleStreamableObject
+ implements Cloneable
{
+ /** This portal's unique identifier. */
+ public short portalId;
+
+ /** This portal's x coordinate (interpreted by the display system). */
+ public int x;
+
+ /** This portal's y coordinate (interpreted by the display system). */
+ public int y;
+
+ /** This portal's y orientation (interpreted by the display system). */
+ public byte orient;
+
/** The scene identifier of the scene to which a body will exit when
* they "use" this portal. */
public int targetSceneId;
- /** The location identifier of the location at which a body will enter
+ /** The portal identifier of the portal at which a body will enter
* the target scene when they "use" this portal. */
- public int targetLocId;
+ public short targetPortalId;
- // documentation inherited
- protected void toString (StringBuffer buf)
+ /**
+ * Returns a location instance configured with the location and
+ * orientation of this portal.
+ */
+ public Location getLocation ()
{
- super.toString(buf);
- buf.append(", targetScene=").append(targetSceneId);
- buf.append(", targetLoc=").append(targetLocId);
+ return new Location(x, y, orient);
+ }
+
+ /**
+ * Returns a location instance configured with the location and
+ * opposite orientation of this portal. This is useful for when a body
+ * is entering a scene at a portal and we want them to face the
+ * opposite direction (as they are entering via the portal rather than
+ * leaving, which is the natural "orientation" of a portal).
+ */
+ public Location getOppLocation ()
+ {
+ return new Location(x, y, (byte)DirectionUtil.getOpposite(orient));
+ }
+
+ /**
+ * Returns true if the portal has a potentially valid target scene and
+ * portal id (they are not guaranteed to exist, but they are at least
+ * potentially valid values rather than -1 or 0).
+ */
+ public boolean isValid ()
+ {
+ return (targetSceneId > 0) && (targetPortalId > 0);
+ }
+
+ /**
+ * Creates a clone of this instance.
+ */
+ public Object clone ()
+ {
+ try {
+ return (Portal)super.clone();
+ } catch (CloneNotSupportedException cnse) {
+ throw new RuntimeException("Portal.clone() failed " + cnse);
+ }
+ }
+
+ /**
+ * Portal equality is determined by portal id.
+ */
+ public boolean equals (Object other)
+ {
+ if (other instanceof Portal) {
+ Portal oport = (Portal)other;
+ return portalId == oport.portalId;
+ } else {
+ return false;
+ }
+ }
+
+ /** {@link #toString} helper function. */
+ public String orientToString ()
+ {
+ return DirectionUtil.toShortString(orient);
+ }
+
+ /**
+ * Computes a reasonable hashcode for portal instances.
+ */
+ public int hashCode ()
+ {
+ return portalId;
}
}
diff --git a/src/java/com/threerings/whirled/spot/data/SceneLocation.java b/src/java/com/threerings/whirled/spot/data/SceneLocation.java
new file mode 100644
index 000000000..959410cf0
--- /dev/null
+++ b/src/java/com/threerings/whirled/spot/data/SceneLocation.java
@@ -0,0 +1,54 @@
+//
+// $Id: SceneLocation.java,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.spot.data;
+
+import com.threerings.presents.dobj.DSet;
+
+/**
+ * Extends {@link Location} with the data and functionality needed to
+ * represent a particular user's location in a scene.
+ */
+public class SceneLocation extends Location
+ implements DSet.Entry
+{
+ /** The oid of the body that occupies this location. */
+ public int bodyOid;
+
+ /**
+ * Creates a scene location with the specified information.
+ */
+ public SceneLocation (int x, int y, byte orient, int bodyOid)
+ {
+ super(x, y, orient);
+ this.bodyOid = bodyOid;
+ }
+
+ /**
+ * Creates a scene location with the specified information.
+ */
+ public SceneLocation (Location loc, int bodyOid)
+ {
+ super(loc.x, loc.y, loc.orient);
+ this.bodyOid = bodyOid;
+ }
+
+ /**
+ * Creates a blank instance suitable for unserialization.
+ */
+ public SceneLocation ()
+ {
+ }
+
+ // documentation inherited
+ public Comparable getKey ()
+ {
+ if (_key == null) {
+ _key = new Integer(bodyOid);
+ }
+ return _key;
+ }
+
+ /** Used for {@link #geyKey}. */
+ protected transient Integer _key;
+}
diff --git a/src/java/com/threerings/whirled/spot/data/SpotMarshaller.java b/src/java/com/threerings/whirled/spot/data/SpotMarshaller.java
index 6f7987c1c..0027cc61e 100644
--- a/src/java/com/threerings/whirled/spot/data/SpotMarshaller.java
+++ b/src/java/com/threerings/whirled/spot/data/SpotMarshaller.java
@@ -1,5 +1,5 @@
//
-// $Id: SpotMarshaller.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
+// $Id: SpotMarshaller.java,v 1.3 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.data;
@@ -10,6 +10,7 @@ import com.threerings.whirled.client.SceneService.SceneMoveListener;
import com.threerings.whirled.data.SceneMarshaller.SceneMoveMarshaller;
import com.threerings.whirled.spot.client.SpotService;
import com.threerings.whirled.spot.client.SpotService.ChangeLocListener;
+import com.threerings.whirled.spot.data.Location;
/**
* Provides the implementation of the {@link SpotService} interface
@@ -17,10 +18,6 @@ import com.threerings.whirled.spot.client.SpotService.ChangeLocListener;
* on the server. Also provides an implementation of the response listener
* interfaces that marshall the response arguments and deliver them back
* to the requesting client.
- *
- * Generated from Generated from Scrutinizers of the code might cringe at the somewhat inefficient
- * array manipulation used to preserve the integrity of the arrays
- * returned by {@link #getLocations} and {@link #getPortals}. Since we
- * expect reading to happen more often than modifying, this seemed a
- * reasonable tradeoff, and one should also note that this class will only
- * ever be used in the offline editor and not in any performance
- * constrained runtime system.
- *
- * @see com.threerings.whirled.tools.EditableScene
- */
-public class EditableSpotSceneImpl extends EditableSceneImpl
- implements EditableSpotScene
-{
- /**
- * Creates an instance that will create and use a blank scene model.
- */
- public EditableSpotSceneImpl ()
- {
- this(EditableSpotSceneModel.blankSpotSceneModel());
- }
-
- /**
- * Creates an instance that will obtain data from the supplied scene
- * model and update it when changes are made.
- */
- public EditableSpotSceneImpl (EditableSpotSceneModel model)
- {
- this(model, new DisplaySpotSceneImpl(model.spotSceneModel, null));
- }
-
- /**
- * Creates an instance that will obtain data from the supplied scene
- * model and update it when changes are made. It will delegate to the
- * supplied display spot scene instead of creating its own delegate.
- */
- public EditableSpotSceneImpl (
- EditableSpotSceneModel model, DisplaySpotSceneImpl delegate)
- {
- super(model, delegate);
-
- // keep track of these
- _model = model.spotSceneModel;
- _emodel = model;
- _delegate = delegate;
-
- // go through and replace the plain portals with editable portals
- // (oh the machinations we have to go through for the lack of
- // multiple inheritance)
- List portals = _delegate.getPortals();
- for (int i = 0; i < portals.size(); i++) {
- EditablePortal port = dupePortal((Portal)portals.get(i));;
- port.name = _emodel.portalNames[i];
- port.targetSceneName = (String)_emodel.neighborNames.get(i);
- port.targetPortalName = _emodel.targetPortalNames[i];
- portals.set(i, port);
- }
-
- // determine the highest location id in use by this scene
- Iterator iter = _delegate.getLocations().iterator();
- while (iter.hasNext()) {
- _nextLocationId = Math.max(_nextLocationId,
- ((Location)iter.next()).locationId);
- }
- }
-
- /**
- * Constructs an editable portal with the same configuration as the
- * supplied regular portal.
- */
- protected EditablePortal dupePortal (Portal source)
- {
- EditablePortal port = new EditablePortal();
- port.locationId = source.locationId;
- port.x = source.x;
- port.y = source.y;
- port.orientation = source.orientation;
- port.clusterIndex = source.clusterIndex;
- port.targetSceneId = source.targetSceneId;
- port.targetLocId = source.targetLocId;
- return port;
- }
-
- // documentation inherited
- public int getDefaultEntranceId ()
- {
- return _delegate.getDefaultEntranceId();
- }
-
- // documentation inherited
- public List getLocations ()
- {
- return _delegate.getLocations();
- }
-
- // documentation inherited
- public int getLocationIndex (int locationId)
- {
- return _delegate.getLocationIndex(locationId);
- }
-
- // documentation inherited
- public Location getLocation (int locationId)
- {
- return _delegate.getLocation(locationId);
- }
-
- // documentation inherited
- public List getPortals ()
- {
- return _delegate.getPortals();
- }
-
- // documentation inherited
- public void setDefaultEntranceId (int defaultEntranceId)
- {
- _model.defaultEntranceId = defaultEntranceId;
- }
-
- // documentation inherited
- public int getNextLocationId ()
- {
- return ++_nextLocationId;
- }
-
- // documentation inherited
- public void addLocation (Location loc)
- {
- // add the location to the end of the location list
- _delegate.getLocations().add(loc);
-
- // make sure we've got the highest location id in our next
- // location id field
- _nextLocationId = Math.max(_nextLocationId, loc.locationId);
- }
-
- // documentation inherited
- public void removeLocation (Location loc)
- {
- // remove the location from the list
- _delegate.getLocations().remove(loc);
- }
-
- // documentation inherited
- public void addPortal (EditablePortal eport)
- {
- // add it to the locations lists as well
- addLocation(eport);
-
- // now add it to the end of the _portals list
- _delegate.getPortals().add(eport);
- }
-
- // documentation inherited
- public void removePortal (EditablePortal eport)
- {
- // remove it from the locations list
- removeLocation(eport);
-
- // and remove it from the portals list
- _delegate.getPortals().remove(eport);
- }
-
- // documentation inherited
- public EditableSpotSceneModel getSpotSceneModel ()
- {
- flushToModel();
- return _emodel;
- }
-
- /**
- * This ensures that the modifications we've made to the location and
- * portal arrays are flushed to the model. It is called before
- * returning our model back to the caller.
- */
- protected void flushToModel ()
- {
- super.flushToModel();
-
- List locations = _delegate.getLocations();
-
- // flush the locations
- int lcount = locations.size();
- _model.locationIds = new int[lcount];
- _model.locationX = new int[lcount];
- _model.locationY = new int[lcount];
- _model.locationOrients = new int[lcount];
- _model.locationClusters = new int[lcount];
-
- for (int i = 0; i < lcount; i++) {
- Location loc = (Location)locations.get(i);
- _model.locationIds[i] = loc.locationId;
- _model.locationX[i] = loc.x;
- _model.locationY[i] = loc.y;
- _model.locationOrients[i] = loc.orientation;
- _model.locationClusters[i] = loc.clusterIndex;
- }
-
- // flush the portals
- List portals = _delegate.getPortals();
- int pcount = portals.size();
- _model.portalIds = new int[pcount];
- _model.neighborIds = new int[pcount];
- _model.targetLocIds = new int[pcount];
- _emodel.neighborNames = new ArrayList();
- _emodel.portalNames = new String[pcount];
- _emodel.targetPortalNames = new String[pcount];
-
- for (int i = 0; i < pcount; i++) {
- EditablePortal port = (EditablePortal)portals.get(i);
- _model.portalIds[i] = port.locationId;
- _model.neighborIds[i] = port.targetSceneId;
- _model.targetLocIds[i] = port.targetLocId;
- _emodel.portalNames[i] = port.name;
- _emodel.neighborNames.add(port.targetSceneName);
- _emodel.targetPortalNames[i] = port.targetPortalName;
- }
- }
-
- /** Our spot scene model. */
- protected SpotSceneModel _model;
-
- /** Our editable spot scene model. */
- protected EditableSpotSceneModel _emodel;
-
- /** Our display spot scene delegate. */
- protected DisplaySpotSceneImpl _delegate;
-
- /** A location id counter used for assigning ids to new locations. */
- protected int _nextLocationId;
-}
diff --git a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneModel.java b/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneModel.java
deleted file mode 100644
index d520e219a..000000000
--- a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneModel.java
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// $Id: EditableSpotSceneModel.java,v 1.3 2001/12/12 02:47:17 mdb Exp $
-
-package com.threerings.whirled.tools.spot;
-
-import com.samskivert.util.StringUtil;
-
-import com.threerings.whirled.spot.data.SpotSceneModel;
-import com.threerings.whirled.tools.EditableSceneModel;
-
-public class EditableSpotSceneModel extends EditableSceneModel
-{
- /** The spot scene model that we extend with editable info. */
- public SpotSceneModel spotSceneModel;
-
- /** The names of the portals in this scene. */
- public String[] portalNames;
-
- /** The names of the portals in neighboring scenes to which our
- * portals link. */
- public String[] targetPortalNames;
-
- // documentation inherited
- public Object clone ()
- throws CloneNotSupportedException
- {
- return cloneWithDelegate((SpotSceneModel)spotSceneModel.clone());
- }
-
- // documentation inherited
- protected Object cloneWithDelegate (SpotSceneModel spotSceneModel)
- throws CloneNotSupportedException
- {
- EditableSpotSceneModel essm = (EditableSpotSceneModel)
- super.cloneWithDelegate(spotSceneModel);
- essm.spotSceneModel = spotSceneModel;
- return essm;
- }
-
- /**
- * Derived classes override this to tack their 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 the human readable name of this scene.
- */
- public void setName (String name);
-
- /**
- * 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);
-
- /**
- * Returns the names of the neighbors of this scene.
- */
- public ArrayList getNeighborNames ();
-
- /**
- * Adds a neighbor to this scene. If the neighbor is already listed
- * among the neighbors, it will not be added again.
- */
- public void addNeighbor (String neighborName);
-
- /**
- * Adds a neighbor to this scene.
- *
- * @return true if the neighbor was removed, false if they were not in
- * the neighbor list.
- */
- public boolean removeNeighbor (String neighborName);
-
- /**
- * Implementations must provide an editable 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 EditableSceneModel getSceneModel ();
-}
diff --git a/src/java/com/threerings/whirled/tools/EditableSceneImpl.java b/src/java/com/threerings/whirled/tools/EditableSceneImpl.java
deleted file mode 100644
index e5137b6ed..000000000
--- a/src/java/com/threerings/whirled/tools/EditableSceneImpl.java
+++ /dev/null
@@ -1,144 +0,0 @@
-//
-// $Id: EditableSceneImpl.java,v 1.7 2003/01/31 23:10:46 mdb Exp $
-
-package com.threerings.whirled.tools;
-
-import java.util.ArrayList;
-
-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 implements EditableScene
-{
- /**
- * Creates an instance that will create and use a blank scene model.
- */
- public EditableSceneImpl ()
- {
- this(EditableSceneModel.blankSceneModel());
- }
-
- /**
- * Creates an instance that will obtain data from the supplied scene
- * model and update it when changes are made.
- */
- public EditableSceneImpl (EditableSceneModel model)
- {
- this(model, new DisplaySceneImpl(model.sceneModel, null));
- }
-
- /**
- * Creates an instance that will obtain data from the supplied scene
- * model and update it when changes are made. It will delegate to the
- * supplied display scene instead of creating its own delegate.
- */
- public EditableSceneImpl (
- EditableSceneModel model, DisplaySceneImpl delegate)
- {
- _model = model.sceneModel;
- _emodel = model;
- _delegate = delegate;
- }
-
- // documentation inherited
- public int getId ()
- {
- return _delegate.getId();
- }
-
- // documentation inherited
- public String getName ()
- {
- return _delegate.getName();
- }
-
- // documentation inherited
- public int getVersion ()
- {
- return _delegate.getVersion();
- }
-
- // documentation inherited
- public int[] getNeighborIds ()
- {
- return _delegate.getNeighborIds();
- }
-
- // documentation inherited
- public PlaceConfig getPlaceConfig ()
- {
- return _delegate.getPlaceConfig();
- }
-
- // documentation inherited
- public void setId (int sceneId)
- {
- _model.sceneId = sceneId;
- }
-
- // documentation inherited
- public void setName (String name)
- {
- _model.sceneName = name;
- }
-
- // documentation inherited
- public void setVersion (int version)
- {
- _model.version = version;
- }
-
- // documentation inherited
- public void setNeighborIds (int[] neighborIds)
- {
- _model.neighborIds = neighborIds;
- }
-
- // documentation inherited
- public ArrayList getNeighborNames ()
- {
- return _emodel.neighborNames;
- }
-
- // documentation inherited
- public void addNeighbor (String neighborName)
- {
- if (!_emodel.neighborNames.contains(neighborName)) {
- _emodel.neighborNames.add(neighborName);
- }
- }
-
- // documentation inherited
- public boolean removeNeighbor (String neighborName)
- {
- return _emodel.neighborNames.remove(neighborName);
- }
-
- // documentation inherited
- public EditableSceneModel getSceneModel ()
- {
- flushToModel();
- return _emodel;
- }
-
- /**
- * Derived classes should override this method and flush any editable
- * modifications to the scene model when this method is called.
- */
- protected void flushToModel ()
- {
- }
-
- /** A reference to our scene model. */
- protected SceneModel _model;
-
- /** A reference to our editable scene model. */
- protected EditableSceneModel _emodel;
-
- /** Our display scene delegate. */
- protected DisplaySceneImpl _delegate;
-}
diff --git a/src/java/com/threerings/whirled/tools/EditableSceneModel.java b/src/java/com/threerings/whirled/tools/EditableSceneModel.java
deleted file mode 100644
index 0bb385daa..000000000
--- a/src/java/com/threerings/whirled/tools/EditableSceneModel.java
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// $Id: EditableSceneModel.java,v 1.4 2001/12/12 19:06:15 mdb Exp $
-
-package com.threerings.whirled.tools;
-
-import java.util.ArrayList;
-import com.samskivert.util.StringUtil;
-
-import com.threerings.whirled.data.SceneModel;
-
-/**
- * The editable scene model contains information above and beyond the
- * regular scene model that is necessary for editing and loading scenes.
- */
-public class EditableSceneModel
-{
- /** The scene model that we extend. */
- public SceneModel sceneModel;
-
- /** The human readable name of this scene's neighbors. */
- public ArrayList neighborNames;
-
- /**
- * Generates a string representation of this scene model.
- */
- public String toString ()
- {
- StringBuffer buf = new StringBuffer("[");
- delegatesToString(buf);
- toString(buf);
- return buf.append("]").toString();
- }
-
- // documentation inherited
- public Object clone ()
- throws CloneNotSupportedException
- {
- return cloneWithDelegate((SceneModel)sceneModel.clone());
- }
-
- // documentation inherited
- protected Object cloneWithDelegate (SceneModel sceneModel)
- throws CloneNotSupportedException
- {
- EditableSceneModel esm = (EditableSceneModel)super.clone();
- esm.sceneModel = sceneModel;
- return esm;
- }
-
- /**
- * Derived classes override this to tack their Generated from Generated from toString
- * data on to the string buffer.
- */
- protected void toString (StringBuffer buf)
- {
- buf.append("sceneId=").append(sceneId);
- buf.append(", name=").append(sceneName);
- buf.append(", version=").append(version);
- buf.append(", neighborIds=").append(StringUtil.toString(neighborIds));
- }
-
/**
* Creates and returns a blank scene model.
*/
@@ -84,8 +70,7 @@ public class SceneModel extends SimpleStreamableObject
protected static void populateBlankSceneModel (SceneModel model)
{
model.sceneId = -1;
- model.sceneName = "super.applyToScene.
+ */
+ public void apply (SceneModel model)
+ {
+ // increment the version; disallowing integer overflow
+ model.version = Math.max(_targetVersion + 1, model.version);
+
+ // sanity check for the amazing two billion updates
+ if (model.version == _targetVersion) {
+ Log.warning("Egads! This scene has been updated two billion " +
+ "times [model=" + model + ", update=" + this + "].");
+ }
+ }
+
+ /**
+ * Generates a string representation of this instance.
+ */
+ public String toString ()
+ {
+ StringBuffer buf = new StringBuffer("[");
+ toString(buf);
+ return buf.append("]").toString();
+ }
+
+ /**
+ * An extensible mechanism for generating a string representation of
+ * this instance.
+ */
+ protected void toString (StringBuffer buf)
+ {
+ buf.append("sceneId=").append(_targetId);
+ buf.append(", version=").append(_targetVersion);
+ }
+
+ /** The version number of the scene on which we operate. */
+ protected int _targetId;
+
+ /** The version number of the scene on which we operate. */
+ protected int _targetVersion;
+}
diff --git a/src/java/com/threerings/whirled/server/DefaultRuntimeSceneFactory.java b/src/java/com/threerings/whirled/server/DefaultRuntimeSceneFactory.java
deleted file mode 100644
index f13f733ba..000000000
--- a/src/java/com/threerings/whirled/server/DefaultRuntimeSceneFactory.java
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// $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
deleted file mode 100644
index 8dc3aa1d8..000000000
--- a/src/java/com/threerings/whirled/server/RuntimeScene.java
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// $Id: RuntimeScene.java,v 1.3 2003/02/04 17:25:09 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.
- *
- * 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 human readable name of this scene.
- */
- public String getName ();
-
- /**
- * Returns the version number of this scene.
- */
- public int getVersion ();
-
- /**
- * Updates the version number of this scene and immediately updates
- * our associated scene model.
- */
- public void setVersion (int version);
-
- /**
- * 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
deleted file mode 100644
index f32ff592d..000000000
--- a/src/java/com/threerings/whirled/server/RuntimeSceneFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// $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
deleted file mode 100644
index d0e78f8e2..000000000
--- a/src/java/com/threerings/whirled/server/RuntimeSceneImpl.java
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// $Id: RuntimeSceneImpl.java,v 1.3 2003/02/04 17:25:09 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 String getName ()
- {
- return _model.sceneName;
- }
-
- // documentation inherited
- public int getVersion ()
- {
- return _model.version;
- }
-
- // documentation inherited from interface
- public void setVersion (int version)
- {
- _model.version = 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/SceneDispatcher.java b/src/java/com/threerings/whirled/server/SceneDispatcher.java
index e4339d2a1..b511ed681 100644
--- a/src/java/com/threerings/whirled/server/SceneDispatcher.java
+++ b/src/java/com/threerings/whirled/server/SceneDispatcher.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneDispatcher.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
+// $Id: SceneDispatcher.java,v 1.3 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.server;
@@ -13,13 +13,10 @@ import com.threerings.whirled.client.SceneService;
import com.threerings.whirled.client.SceneService.SceneMoveListener;
import com.threerings.whirled.data.SceneMarshaller;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
/**
* Dispatches requests to the {@link SceneProvider}.
- *
- *
- * $Id: SceneDispatcher.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
- *
*/
public class SceneDispatcher extends InvocationDispatcher
{
@@ -55,4 +52,6 @@ public class SceneDispatcher extends InvocationDispatcher
super.dispatchRequest(source, methodId, args);
}
}
+
+ // Generated on 14:44:07 02/08/03.
}
diff --git a/src/java/com/threerings/whirled/server/SceneManager.java b/src/java/com/threerings/whirled/server/SceneManager.java
index bfaaf08cb..6036edf3c 100644
--- a/src/java/com/threerings/whirled/server/SceneManager.java
+++ b/src/java/com/threerings/whirled/server/SceneManager.java
@@ -1,10 +1,19 @@
//
-// $Id: SceneManager.java,v 1.11 2003/02/05 00:23:52 mdb Exp $
+// $Id: SceneManager.java,v 1.12 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.server;
+import com.samskivert.io.PersistenceException;
+
import com.threerings.crowd.server.PlaceManager;
+import com.threerings.presents.util.Invoker;
+
+import com.threerings.whirled.Log;
+import com.threerings.whirled.data.Scene;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
+import com.threerings.whirled.server.WhirledServer;
+import com.threerings.whirled.util.UpdateList;
/**
* The scene manager extends the place manager and takes care of basic
@@ -15,37 +24,36 @@ import com.threerings.whirled.data.SceneModel;
public class SceneManager extends PlaceManager
{
/**
- * Returns the runtime scene object (not the scene distributed object)
- * being managed by this scene manager.
+ * Returns the scene object (not the scene distributed object) being
+ * managed by this scene manager.
*/
- public RuntimeScene getScene ()
+ public Scene 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 setSceneData (
- RuntimeScene scene, SceneModel model, SceneRegistry screg)
+ protected void setSceneData (Scene scene, UpdateList updates,
+ SceneRegistry screg)
{
+ // make sure the list and our version of the scene are in
+ // accordance
+ if (!updates.validate(scene.getVersion())) {
+ Log.warning("Provided with invalid updates; flushing " +
+ "[where=" + where() +
+ ", sceneId=" + scene.getId() + "].");
+ // clear out the update list as it will not allow us to bring
+ // clients up to date with our current scene version; instead
+ // they'll have to download the whole thing
+ updates = new UpdateList();
+ }
+
_scene = scene;
- _model = model;
_screg = screg;
+ _updates = updates;
// let derived classes react to the receipt of scene data
gotSceneData();
@@ -85,10 +93,45 @@ public class SceneManager extends PlaceManager
_screg.unmapSceneManager(this);
}
+ /**
+ * When a modification is made to a scene, the scene manager should
+ * update its internal structures, update the {@link Scene} object,
+ * update the repository (either by storing the updated scene
+ * wholesale or more efficiently updating only what has changed), and
+ * then it should create a {@link SceneUpdate} record that can be
+ * delivered to clients to effect the update to the clients's cached
+ * copy of the scene model. This update will be stored persistently
+ * and provided (along with any other accumulated updates) to clients
+ * that later request to enter the scene with an old version of the
+ * scene data. Updates are not stored forever, but a sizable number of
+ * recent updates are stored so that moderately current clients can
+ * apply incremental patches to their scenes rather than redownloading
+ * the entire scenes when they change.
+ */
+ protected void recordUpdate (final SceneUpdate update)
+ {
+ // add it to our in memory update list
+ _updates.addUpdate(update);
+
+ // and store it in the repository
+ WhirledServer.invoker.postUnit(new Invoker.Unit() {
+ public boolean invoke () {
+ try {
+ _screg.getSceneRepository().addUpdate(update);
+ } catch (PersistenceException pe) {
+ Log.warning("Failed to store scene update " +
+ "[update=" + update + ", error=" + pe + "].");
+ }
+ return false;
+ }
+ });
+ }
+
// documentation inherited
public String where ()
{
- return _scene.getName() + " (" + super.where() + ")";
+ return _scene.getName() + " (" + super.where() + ":" +
+ _scene.getId() + ")";
}
// documentation inherited
@@ -98,15 +141,14 @@ public class SceneManager extends PlaceManager
buf.append(", scene=").append(_scene);
}
- /** A reference to our runtime scene implementation which provides a
+ /** A reference to our scene implementation which provides a
* meaningful interpretation of the data in the scene model. */
- protected RuntimeScene _scene;
+ protected Scene _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 list of the updates tracked for this scene. These will be used
+ * to attempt to bring clients up to date efficiently if they request
+ * to enter our scene with old scene model data. */
+ protected UpdateList _updates;
/** A reference to the scene registry so that we can call back to it
* when we're fully initialized. */
diff --git a/src/java/com/threerings/whirled/server/SceneProvider.java b/src/java/com/threerings/whirled/server/SceneProvider.java
index 4caac7d2a..cba2a557b 100644
--- a/src/java/com/threerings/whirled/server/SceneProvider.java
+++ b/src/java/com/threerings/whirled/server/SceneProvider.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneProvider.java,v 1.14 2002/12/14 01:51:00 mdb Exp $
+// $Id: SceneProvider.java,v 1.15 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.server;
@@ -104,9 +104,9 @@ public class SceneProvider
((ScenedBodyObject)source).setSceneId(scmgr.getScene().getId());
// check to see if they need a newer version of the scene data
- SceneModel model = scmgr.getSceneModel();
+ SceneModel model = scmgr.getScene().getSceneModel();
if (sceneVersion < model.version) {
- listener.moveSucceededPlusUpdate(ploid, config, model);
+ listener.moveSucceededWithScene(ploid, config, model);
} else {
listener.moveSucceeded(ploid, config);
}
diff --git a/src/java/com/threerings/whirled/server/SceneRegistry.java b/src/java/com/threerings/whirled/server/SceneRegistry.java
index 3791d27c1..d57ece6c3 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.17 2002/10/06 00:44:58 mdb Exp $
+// $Id: SceneRegistry.java,v 1.18 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.server;
@@ -11,19 +11,23 @@ import com.threerings.presents.util.Invoker;
import com.threerings.presents.server.InvocationManager;
+import com.threerings.crowd.data.PlaceConfig;
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;
+import com.threerings.whirled.util.SceneFactory;
+import com.threerings.whirled.util.UpdateList;
/**
- * The scene registry is responsible for the management of all runtime
- * scenes. It handles interaction with the scene repository and ensures
- * that scenes are loaded into memory when needed and flushed from memory
- * when not needed.
+ * The scene registry is responsible for the management of all scenes. It
+ * handles interaction with the scene repository and ensures that scenes
+ * are loaded into memory when needed and flushed from memory when not
+ * needed.
*
* cluster
+ * the client will be made to create a new cluster, join and existing
+ * cluster or join no cluster at all.
+ *
+ * @param loc the new location to which to move.
+ * @param cluster if zero, a new cluster will be created and assigned
+ * to the calling user; if -1, the calling user will be removed from
+ * any cluster they currently occupy and not made to occupy a new
+ * cluster; if the bodyOid of another user, the calling user will be
+ * made to join the target user's cluster.
+ * @param obs will be notified of success or failure. Most client
+ * entities find out about location changes via changes to the
+ * occupant info data, but the initiator of a location change request
+ * can be notified of its success or failure, primarily so that it can
+ * act in anticipation of a successful location change (like by
+ * starting a sprite moving toward the new location), but backtrack if
+ * it finds out that the location change failed.
*/
- public void changeLocation (int locationId, ChangeObserver obs)
+ public void changeLocation (Location loc, int cluster, ChangeObserver obs)
{
// refuse if there's a pending location change or if we're already
// at the specified location
- if ((locationId == _locationId) || (_pendingLocId != -1)) {
+ if (loc.equals(_location) || (_pendingLoc != null)) {
+ Log.info("Not going to " + loc + "; we're at " + _location +
+ " and we're headed to " + _pendingLoc + ".");
return;
}
- // make sure we're currently in a scene
- DisplaySpotScene scene = (DisplaySpotScene)_scdir.getScene();
+ SpotScene scene = (SpotScene)_scdir.getScene();
if (scene == null) {
Log.warning("Requested to change locations, but we're not " +
- "currently in any scene [locId=" + locationId + "].");
+ "currently in any scene [loc=" + loc + "].");
return;
}
- // make sure the specified location is in the current scene
- Location loc = scene.getLocation(locationId);
- if (loc == null) {
- Log.warning("Requested to change to a location that's not " +
- "in the current scene [locs=" + StringUtil.toString(
- scene.getLocations().iterator()) +
- ", locId=" + locationId + "].");
- return;
- }
+ Log.info("Changing location [loc=" + loc + ", clus=" + cluster + "].");
- // make a note that we're changing to this location
- _pendingLocId = locationId;
+ _pendingLoc = (Location)loc.clone();
_changeObserver = obs;
-
- // and send the location change request
- _sservice.changeLoc(_ctx.getClient(), scene.getId(), locationId, this);
+ _sservice.changeLoc(_ctx.getClient(), loc, cluster, this);
}
/**
@@ -225,80 +219,37 @@ public class SpotSceneDirector extends BasicDirector
public boolean requestClusterSpeak (String message, byte mode)
{
// make sure we're currently in a scene
- DisplaySpotScene scene = (DisplaySpotScene)_scdir.getScene();
+ SpotScene scene = (SpotScene)_scdir.getScene();
if (scene == null) {
Log.warning("Requested to speak to cluster, but we're not " +
"currently in any scene [message=" + message + "].");
return false;
}
- // make sure we're in a location
- Location loc = scene.getLocation(_locationId);
- if (loc == null) {
- Log.info("Ignoring cluster speak as we're not in a valid " +
- "location [locId=" + _locationId + "].");
+ // make sure we're part of a cluster
+ if (_self.getClusterOid() <= 0) {
+ Log.info("Ignoring cluster speak as we're not in a cluster " +
+ "[cloid=" + _self.getClusterOid() + "].");
return false;
}
- // make sure the location has an associated cluster
- if (loc.clusterIndex == -1) {
- Log.info("Ignoring cluster speak as our location has no " +
- "cluster [loc=" + loc + "].");
- return false;
- }
-
- // we're all clear to go
- _sservice.clusterSpeak(_ctx.getClient(), scene.getId(), _locationId,
- message, mode);
+ _sservice.clusterSpeak(_ctx.getClient(), message, mode);
return true;
}
- // documentation inherited
- protected void fetchServices (Client client)
- {
- _sservice = (SpotService)client.requireService(SpotService.class);
- }
-
- // documentation inherited
- public void clientDidLogoff (Client client)
- {
- super.clientDidLogoff(client);
-
- // clear out our business
- _locationId = -1;
- _pendingLocId = -1;
- _changeObserver = null;
- _clobj = null;
- _sservice = null;
- }
-
// documentation inherited from interface
- public void changeLocSucceeded (int clusterOid)
+ public void changeLocSucceeded ()
{
ChangeObserver obs = _changeObserver;
- _locationId = _pendingLocId;
+ _location = _pendingLoc;
// clear out our pending location info
- _pendingLocId = -1;
+ _pendingLoc = null;
_changeObserver = null;
- // determine if our cluster oid changed (which we only care about
- // if we're doing cluster chat)
- if (_chatdir != null) {
- int oldOid = (_clobj == null) ? -1 : _clobj.getOid();
- if (clusterOid != oldOid) {
- DObjectManager omgr = _ctx.getDObjectManager();
- // remove our old subscription if necessary
- clearCluster();
- // create a new subscription (we'll wire it up to the chat
- // director when the subscription completes)
- omgr.subscribeToObject(clusterOid, this);
- }
- }
-
// if we had an observer, let them know things went well
if (obs != null) {
- obs.locationChangeSucceeded(_locationId);
+ obs.locationChangeSucceeded(_location);
}
}
@@ -306,15 +257,15 @@ public class SpotSceneDirector extends BasicDirector
public void requestFailed (String reason)
{
ChangeObserver obs = _changeObserver;
- int locId = _pendingLocId;
+ Location loc = _pendingLoc;
// clear out our pending location info
- _pendingLocId = -1;
+ _pendingLoc = null;
_changeObserver = null;
// if we had an observer, let them know things went well
if (obs != null) {
- obs.locationChangeFailed(locId, reason);
+ obs.locationChangeFailed(loc, reason);
}
}
@@ -340,13 +291,73 @@ public class SpotSceneDirector extends BasicDirector
"[oid=" + oid + ", cause=" + cause + "].");
}
+ // documentation inherited from interface
+ public void attributeChanged (AttributeChangedEvent event)
+ {
+ // if our cluster oid changes from the one we're currently
+ // subscribed to, give it the boot
+ if (_clobj != null && _self.getClusterOid() != _clobj.getOid()) {
+ clearCluster();
+ }
+
+ // if there's a new cluster object, subscribe to it
+ if (_chatdir != null && _self.getClusterOid() > 0) {
+ DObjectManager omgr = _ctx.getDObjectManager();
+ // we'll wire up to the chat director when this completes
+ omgr.subscribeToObject(_self.getClusterOid(), this);
+ }
+ }
+
+ // documentation inherited from interface
+ public void clientDidLogon (Client client)
+ {
+ super.clientDidLogon(client);
+
+ // listen to the client object
+ client.getClientObject().addListener(this);
+ _self = (ClusteredBodyObject)client.getClientObject();
+ }
+
+ // documentation inherited from interface
+ public void clientObjectDidChange (Client client)
+ {
+ super.clientObjectDidChange(client);
+
+ // listen to the client object
+ client.getClientObject().addListener(this);
+ _self = (ClusteredBodyObject)client.getClientObject();
+ }
+
+ // documentation inherited
+ public void clientDidLogoff (Client client)
+ {
+ super.clientDidLogoff(client);
+
+ // clear out our business
+ _location = null;
+ _pendingLoc = null;
+ _changeObserver = null;
+ _sservice = null;
+ clearCluster();
+
+ // stop listening to the client object
+ client.getClientObject().removeListener(this);
+ _self = null;
+ }
+
+ // documentation inherited
+ protected void fetchServices (Client client)
+ {
+ _sservice = (SpotService)client.requireService(SpotService.class);
+ }
+
/**
* Clean up after a few things when we depart from a scene.
*/
protected void handleDeparture ()
{
// clear out our last known location id
- _locationId = -1;
+ _location = null;
// unwire and clear out our cluster chat object if we've got one
clearCluster();
@@ -377,15 +388,18 @@ public class SpotSceneDirector extends BasicDirector
/** The scene director with which we are cooperating. */
protected SceneDirector _scdir;
+ /** A casted reference to our clustered body object. */
+ protected ClusteredBodyObject _self;
+
/** A reference to the chat director with which we coordinate. */
protected ChatDirector _chatdir;
- /** The location id of the location we currently occupy. */
- protected int _locationId = -1;
+ /** The location we currently occupy. */
+ protected Location _location;
- /** The location id on which we have an outstanding change location
+ /** The location to which we have an outstanding change location
* request. */
- protected int _pendingLocId = -1;
+ protected Location _pendingLoc;
/** The cluster chat object for the cluster we currently occupy. */
protected DObject _clobj;
diff --git a/src/java/com/threerings/whirled/spot/client/SpotService.java b/src/java/com/threerings/whirled/spot/client/SpotService.java
index 7337d3ce8..17ba1698e 100644
--- a/src/java/com/threerings/whirled/spot/client/SpotService.java
+++ b/src/java/com/threerings/whirled/spot/client/SpotService.java
@@ -1,5 +1,5 @@
//
-// $Id: SpotService.java,v 1.11 2002/08/14 19:07:57 mdb Exp $
+// $Id: SpotService.java,v 1.12 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.client;
@@ -7,20 +7,25 @@ import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
import com.threerings.whirled.client.SceneService.SceneMoveListener;
+import com.threerings.whirled.spot.data.Location;
/**
- * Defines the mechanism by which the client can request to move between
- * locations within a scene and between scenes (taking exit and entry
- * locations into account). These services should not be used directly,
- * but instead should be accessed via the {@link SpotSceneDirector}.
+ * Defines the mechanism by which the client can request to move around
+ * within a scene and between scenes (taking exit and entry locations into
+ * account). These services should not be used directly, but instead
+ * should be accessed via the {@link SpotSceneDirector}.
*/
public interface SpotService extends InvocationService
{
/**
* Requests to traverse the specified portal.
+ *
+ * @param portalId the portal to be traversed.
+ * @param descSceneVer the version of the destination scene data that
+ * the client has in its local repository.
*/
public void traversePortal (
- Client client, int sceneId, int portalId, int sceneVer,
+ Client client, int portalId, int destSceneVer,
SceneMoveListener listener);
/**
@@ -29,25 +34,32 @@ public interface SpotService extends InvocationService
public static interface ChangeLocListener extends InvocationListener
{
/**
- * Called when the change location request succeeded.
- *
- * @param clusterOid the object id of the cluster object
- * associated with the new location.
+ * Called when the change location request succeeds.
*/
- public void changeLocSucceeded (int clusterOid);
+ public void changeLocSucceeded ();
}
/**
- * Requests that this client's body be made to occupy the specified
+ * Requests that this client's body be made to move to the specified
* location.
+ *
+ * @param loc the location to which to move.
+ * @param cluster if zero, a new cluster will be created and assigned
+ * to the calling user; if -1, the calling user will be removed from
+ * any cluster they currently occupy and not made to occupy a new
+ * cluster; if the bodyOid of another user, the calling user will be
+ * made to join the target user's cluster.
*/
- public void changeLoc (Client client, int sceneId, int locationId,
+ public void changeLoc (Client client, Location loc, int cluster,
ChangeLocListener listener);
/**
* Requests that the supplied message be delivered to listeners in the
* cluster to which the specified location belongs.
+ *
+ * @param message the text of the message to be spoken.
+ * @param mode an associated mode constant that can be used to
+ * identify different kinds of "speech" (emote, thought bubble, etc.).
*/
- public void clusterSpeak (Client client, int sceneId, int locationId,
- String message, byte mode);
+ public void clusterSpeak (Client client, String message, byte mode);
}
diff --git a/src/java/com/threerings/whirled/spot/data/ClusterObject.dobj b/src/java/com/threerings/whirled/spot/data/ClusterObject.dobj
index d694be76d..cec127ea8 100644
--- a/src/java/com/threerings/whirled/spot/data/ClusterObject.dobj
+++ b/src/java/com/threerings/whirled/spot/data/ClusterObject.dobj
@@ -1,14 +1,18 @@
//
-// $Id: ClusterObject.dobj,v 1.1 2002/11/04 22:33:39 mdb Exp $
+// $Id: ClusterObject.dobj,v 1.2 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.data;
import com.threerings.presents.dobj.DObject;
+import com.threerings.presents.dobj.OidList;
/**
- * Used to dispatch chat in clusters. Contains no other information at the
- * moment.
+ * Used to dispatch chat in clusters.
*/
public class ClusterObject extends DObject
{
+ /**
+ * Tracks the oid of the body objects that occupy this cluster.
+ */
+ public OidList occupants = new OidList();
}
diff --git a/src/java/com/threerings/whirled/spot/data/ClusterObject.java b/src/java/com/threerings/whirled/spot/data/ClusterObject.java
index 48a3ddf9c..74ed84bbe 100644
--- a/src/java/com/threerings/whirled/spot/data/ClusterObject.java
+++ b/src/java/com/threerings/whirled/spot/data/ClusterObject.java
@@ -1,14 +1,41 @@
//
-// $Id: ClusterObject.java,v 1.1 2002/11/04 22:33:39 mdb Exp $
+// $Id: ClusterObject.java,v 1.2 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.data;
import com.threerings.presents.dobj.DObject;
+import com.threerings.presents.dobj.OidList;
/**
- * Used to dispatch chat in clusters. Contains no other information at the
- * moment.
+ * Used to dispatch chat in clusters.
*/
public class ClusterObject extends DObject
{
+ /** The field name of the occupants field. */
+ public static final String OCCUPANTS = "occupants";
+
+ /**
+ * Tracks the oid of the body objects that occupy this cluster.
+ */
+ public OidList occupants = new OidList();
+
+ /**
+ * Requests that the specified oid be added to the
+ * occupants oid list. The list will not change until the
+ * event is actually propagated through the system.
+ */
+ public void addToOccupants (int oid)
+ {
+ requestOidAdd(OCCUPANTS, oid);
+ }
+
+ /**
+ * Requests that the specified oid be removed from the
+ * occupants oid list. The list will not change until the
+ * event is actually propagated through the system.
+ */
+ public void removeFromOccupants (int oid)
+ {
+ requestOidRemove(OCCUPANTS, oid);
+ }
}
diff --git a/src/java/com/threerings/whirled/spot/data/ClusteredBodyObject.java b/src/java/com/threerings/whirled/spot/data/ClusteredBodyObject.java
new file mode 100644
index 000000000..b9f6ee778
--- /dev/null
+++ b/src/java/com/threerings/whirled/spot/data/ClusteredBodyObject.java
@@ -0,0 +1,25 @@
+//
+// $Id: ClusteredBodyObject.java,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.spot.data;
+
+import com.threerings.crowd.data.BodyObject;
+import com.threerings.whirled.data.ScenedBodyObject;
+
+/**
+ * Defines some required methods for a {@link BodyObject} that is to
+ * participate in the Whirled Spot system.
+ */
+public interface ClusteredBodyObject extends ScenedBodyObject
+{
+ /**
+ * Returns the oid of the cluster to which this user currently
+ * belongs.
+ */
+ public int getClusterOid ();
+
+ /**
+ * Sets the oid of the cluster to which this user currently belongs.
+ */
+ public void setClusterOid (int clusterOid);
+}
diff --git a/src/java/com/threerings/whirled/spot/data/Location.java b/src/java/com/threerings/whirled/spot/data/Location.java
index 730eb982f..558f7a152 100644
--- a/src/java/com/threerings/whirled/spot/data/Location.java
+++ b/src/java/com/threerings/whirled/spot/data/Location.java
@@ -1,43 +1,75 @@
//
-// $Id: Location.java,v 1.5 2001/12/05 09:14:29 mdb Exp $
+// $Id: Location.java,v 1.6 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.data;
-/**
- * A location represents a place to stand in a scene. More specifically,
- * it is a geometric location in a scene with an orientation that would be
- * assumed by any body sprite standing in that location. Locations may
- * optionally belong to a cluster, which associates them with a group of
- * locations for speaking purposes (bodies in the same cluster can "hear"
- * one another speak).
- */
-public class Location
-{
- /** This location's unique identifier. */
- public int locationId;
+import com.threerings.io.SimpleStreamableObject;
+import com.threerings.util.DirectionCodes;
+import com.threerings.util.DirectionUtil;
- /** This location's x coordinate (interpreted by the display system). */
+/**
+ * Contains information on a scene occupant's position and orientation.
+ */
+public class Location extends SimpleStreamableObject
+ implements Cloneable
+{
+ /** The user's x position (interpreted by the display system). */
public int x;
- /** This location's y coordinate (interpreted by the display system). */
+ /** The user's y position (interpreted by the display system). */
public int y;
- /** This location's y orientation (interpreted by the display system). */
- public int orientation;
+ /** The user's orientation (defined by {@link DirectionCodes}). */
+ public byte orient;
- /** The cluster to which this location belongs or -1 if it belongs to
- * no cluster. */
- public int clusterIndex;
+ /** {@link #toString} helper function. */
+ public String orientToString ()
+ {
+ return DirectionUtil.toShortString(orient);
+ }
/**
- * Location equality is determined by location id.
+ * A zero-argument constructor used when unserializing instances.
+ */
+ public Location ()
+ {
+ }
+
+ /**
+ * Constructs a location with the specified coordinates and
+ * orientation.
+ */
+ public Location (int x, int y, byte orient)
+ {
+ this.x = x;
+ this.y = y;
+ this.orient = orient;
+
+ if (orient == -1) {
+ Thread.dumpStack();
+ }
+ }
+
+ /**
+ * Creates a clone of this instance.
+ */
+ public Object clone ()
+ {
+ try {
+ return (Location)super.clone();
+ } catch (CloneNotSupportedException cnse) {
+ throw new RuntimeException("Location.clone() failed " + cnse);
+ }
+ }
+
+ /**
+ * Location equality is determined by coordinates.
*/
public boolean equals (Object other)
{
if (other instanceof Location) {
Location oloc = (Location)other;
- return locationId == oloc.locationId;
-
+ return (x == oloc.x) && (y == oloc.y);
} else {
return false;
}
@@ -48,29 +80,6 @@ public class Location
*/
public int hashCode ()
{
- return locationId;
- }
-
- /**
- * Generates a string representation of this location instance.
- */
- public String toString ()
- {
- StringBuffer buf = new StringBuffer("[");
- toString(buf);
- return buf.append("]").toString();
- }
-
- /**
- * An efficient, extensible mechanism for generating a string
- * representation of locations and derived classes.
- */
- protected void toString (StringBuffer buf)
- {
- buf.append("id=").append(locationId);
- buf.append(", x=").append(x);
- buf.append(", y=").append(y);
- buf.append(", orient=").append(orientation);
- buf.append(", cluster=").append(clusterIndex);
+ return x ^ y;
}
}
diff --git a/src/java/com/threerings/whirled/spot/data/Portal.java b/src/java/com/threerings/whirled/spot/data/Portal.java
index 178b29442..bd30cdb00 100644
--- a/src/java/com/threerings/whirled/spot/data/Portal.java
+++ b/src/java/com/threerings/whirled/spot/data/Portal.java
@@ -1,37 +1,110 @@
//
-// $Id: Portal.java,v 1.4 2001/12/05 03:38:09 mdb Exp $
+// $Id: Portal.java,v 1.5 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.data;
+import com.threerings.io.SimpleStreamableObject;
+import com.threerings.util.DirectionUtil;
+
/**
- * A portal is a location, but one that represents an exit to another
- * scene rather than a place to stand in the current scene. A body sprite
- * would walk over to a portal's coordinates and then either proceed off
- * of the edge of the display, or open a door and walk through it, or
- * fizzle away in a Star Trekkian transporter style or whatever is
- * appropriate for the game in question. It contains information on the
- * scene to which the body exits when using this portal and the location
- * at which the body sprite should appear in that target scene.
- *
- *
- * $Id: SpotMarshaller.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
- *
*/
public class SpotMarshaller extends InvocationMarshaller
implements SpotService
@@ -34,11 +31,11 @@ public class SpotMarshaller extends InvocationMarshaller
public static final int CHANGE_LOC_SUCCEEDED = 1;
// documentation inherited from interface
- public void changeLocSucceeded (int arg1)
+ public void changeLocSucceeded ()
{
omgr.postEvent(new InvocationResponseEvent(
callerOid, requestId, CHANGE_LOC_SUCCEEDED,
- new Object[] { new Integer(arg1) }));
+ new Object[] { }));
}
// documentation inherited
@@ -47,7 +44,7 @@ public class SpotMarshaller extends InvocationMarshaller
switch (methodId) {
case CHANGE_LOC_SUCCEEDED:
((ChangeLocListener)listener).changeLocSucceeded(
- ((Integer)args[0]).intValue());
+ );
return;
default:
@@ -60,12 +57,12 @@ public class SpotMarshaller extends InvocationMarshaller
public static final int TRAVERSE_PORTAL = 1;
// documentation inherited from interface
- public void traversePortal (Client arg1, int arg2, int arg3, int arg4, SceneMoveListener arg5)
+ public void traversePortal (Client arg1, int arg2, int arg3, SceneMoveListener arg4)
{
- SceneMoveMarshaller listener5 = new SceneMoveMarshaller();
- listener5.listener = arg5;
+ SceneMoveMarshaller listener4 = new SceneMoveMarshaller();
+ listener4.listener = arg4;
sendRequest(arg1, TRAVERSE_PORTAL, new Object[] {
- new Integer(arg2), new Integer(arg3), new Integer(arg4), listener5
+ new Integer(arg2), new Integer(arg3), listener4
});
}
@@ -73,12 +70,12 @@ public class SpotMarshaller extends InvocationMarshaller
public static final int CHANGE_LOC = 2;
// documentation inherited from interface
- public void changeLoc (Client arg1, int arg2, int arg3, ChangeLocListener arg4)
+ public void changeLoc (Client arg1, Location arg2, int arg3, ChangeLocListener arg4)
{
ChangeLocMarshaller listener4 = new ChangeLocMarshaller();
listener4.listener = arg4;
sendRequest(arg1, CHANGE_LOC, new Object[] {
- new Integer(arg2), new Integer(arg3), listener4
+ arg2, new Integer(arg3), listener4
});
}
@@ -86,12 +83,12 @@ public class SpotMarshaller extends InvocationMarshaller
public static final int CLUSTER_SPEAK = 3;
// documentation inherited from interface
- public void clusterSpeak (Client arg1, int arg2, int arg3, String arg4, byte arg5)
+ public void clusterSpeak (Client arg1, String arg2, byte arg3)
{
sendRequest(arg1, CLUSTER_SPEAK, new Object[] {
- new Integer(arg2), new Integer(arg3), arg4, new Byte(arg5)
+ arg2, new Byte(arg3)
});
}
- // Class file generated on 12:33:05 08/20/02.
+ // Generated on 10:09:04 02/05/03.
}
diff --git a/src/java/com/threerings/whirled/spot/data/SpotOccupantInfo.java b/src/java/com/threerings/whirled/spot/data/SpotOccupantInfo.java
deleted file mode 100644
index 880dce39b..000000000
--- a/src/java/com/threerings/whirled/spot/data/SpotOccupantInfo.java
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// $Id: SpotOccupantInfo.java,v 1.3 2002/06/20 22:13:20 mdb Exp $
-
-package com.threerings.whirled.spot.data;
-
-import com.samskivert.util.StringUtil.Formatter;
-
-import com.threerings.crowd.data.OccupantInfo;
-
-/**
- * The spot services extend the basic occupant info with information on
- * which location within the scene a user occupies.
- */
-public class SpotOccupantInfo extends OccupantInfo
-{
- /** The id of the location occupied by this user or -1 if they occupy
- * no location. */
- public int locationId;
-
- /** Used to log just the user oids and location ids of users in the
- * occupantInfo set when debugging. */
- public static final Formatter OIDS_AND_LOCS = new Formatter() {
- public String toString (Object object) {
- SpotOccupantInfo soi = (SpotOccupantInfo)object;
- return "[" + soi.getBodyOid() + ", " + soi.locationId + "]";
- }
- };
-}
diff --git a/src/java/com/threerings/whirled/spot/data/SpotScene.java b/src/java/com/threerings/whirled/spot/data/SpotScene.java
new file mode 100644
index 000000000..c3faeb63d
--- /dev/null
+++ b/src/java/com/threerings/whirled/spot/data/SpotScene.java
@@ -0,0 +1,55 @@
+//
+// $Id: SpotScene.java,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.spot.data;
+
+import java.util.Iterator;
+
+/**
+ * Makes available the spot scene information that the server needs to do
+ * its business.
+ */
+public interface SpotScene
+{
+ /**
+ * Returns a {@link Portal} object for the portal with the specified
+ * id or null if no portal exists with that id.
+ */
+ public Portal getPortal (int portalId);
+
+ /**
+ * Returns the number of portals in this scene.
+ */
+ public int getPortalCount ();
+
+ /**
+ * Returns an iterator over the portals in this scene.
+ */
+ public Iterator getPortals ();
+
+ /**
+ * Returns the portal that represents the default entrance to this
+ * scene. If a body enters the scene at logon time rather than
+ * entering from some other scene, this is the portal at which they
+ * would appear.
+ */
+ public Portal getDefaultEntrance ();
+
+ /**
+ * Adds a portal to this scene, immediately making the requisite
+ * modifications to the underlying scene model. A portal id will be
+ * assigned to the portal by this method.
+ */
+ public void addPortal (Portal portal);
+
+ /**
+ * Removes the specified portal from the scene.
+ */
+ public void removePortal (Portal portal);
+
+ /**
+ * Sets the default entrance in this scene, immediately making the
+ * requisite modifications to the underlying scene model.
+ */
+ public void setDefaultEntrance (Portal portal);
+}
diff --git a/src/java/com/threerings/whirled/spot/data/SpotSceneImpl.java b/src/java/com/threerings/whirled/spot/data/SpotSceneImpl.java
new file mode 100644
index 000000000..c0983d162
--- /dev/null
+++ b/src/java/com/threerings/whirled/spot/data/SpotSceneImpl.java
@@ -0,0 +1,122 @@
+//
+// $Id: SpotSceneImpl.java,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.spot.data;
+
+import java.util.Iterator;
+
+import com.samskivert.util.HashIntMap;
+import com.samskivert.util.ListUtil;
+
+import com.threerings.whirled.spot.Log;
+
+/**
+ * An implementation of the {@link SpotScene} interface.
+ */
+public class SpotSceneImpl
+ implements SpotScene
+{
+ /**
+ * Creates an instance that will obtain data from the supplied spot
+ * scene model.
+ */
+ public SpotSceneImpl (SpotSceneModel smodel)
+ {
+ _smodel = smodel;
+
+ for (int ii = 0, ll = _smodel.portals.length; ii < ll; ii++) {
+ Portal port = _smodel.portals[ii];
+ _portals.put(port.portalId, port);
+ }
+ }
+
+ /**
+ * Instantiates a blank scene implementation.
+ */
+ public SpotSceneImpl ()
+ {
+ _smodel = new SpotSceneModel();
+ }
+
+ // documentation inherited from interface
+ public Portal getPortal (int portalId)
+ {
+ return (Portal)_portals.get(portalId);
+ }
+
+ // documentation inherited from interface
+ public int getPortalCount ()
+ {
+ return _portals.size();
+ }
+
+ // documentation inherited from interface
+ public Iterator getPortals ()
+ {
+ return _portals.values().iterator();
+ }
+
+ // documentation inherited from interface
+ public Portal getDefaultEntrance ()
+ {
+ return getPortal(_smodel.defaultEntranceId);
+ }
+
+ // documentation inherited from interface
+ public void addPortal (Portal portal)
+ {
+ // compute a new portal id for our friend the portal
+ portal.portalId = 0;
+ for (short ii = 1; ii < MAX_PORTAL_ID; ii++) {
+ if (!_portals.containsKey(ii)) {
+ portal.portalId = ii;
+ break;
+ }
+ }
+ if (portal.portalId == 0) {
+ Log.warning("Unable to assign id to new portal " +
+ "[scene=" + this + "].");
+ return;
+ }
+
+ // add this beyotch to our model
+ _smodel.addPortal(portal);
+
+ // and slap it into our table
+ _portals.put(portal.portalId, portal);
+ }
+
+ // documentation inherited from interface
+ public void removePortal (Portal portal)
+ {
+ // remove the portal from our mapping
+ _portals.remove(portal.portalId);
+
+ // remove it from the model
+ _smodel.removePortal(portal);
+ }
+
+ /**
+ * Used when we're being parsed from an XML scene model.
+ */
+ public void setDefaultEntranceId (int defaultEntranceId)
+ {
+ _smodel.defaultEntranceId = defaultEntranceId;
+ }
+
+ // documentation inherited from interface
+ public void setDefaultEntrance (Portal portal)
+ {
+ _smodel.defaultEntranceId = (portal == null) ? -1 : portal.portalId;
+ }
+
+ /** A casted reference to our scene model. */
+ protected SpotSceneModel _smodel;
+
+ /** A mapping from portal id to portal. */
+ protected HashIntMap _portals = new HashIntMap();
+
+ /** We don't allow more than ~32k portals in a scene. Things would
+ * slow down *way* before we got there. */
+ protected static final int MAX_PORTAL_ID = Short.MAX_VALUE;
+}
diff --git a/src/java/com/threerings/whirled/spot/data/SpotSceneModel.java b/src/java/com/threerings/whirled/spot/data/SpotSceneModel.java
index 122dfebbc..1679b7d20 100644
--- a/src/java/com/threerings/whirled/spot/data/SpotSceneModel.java
+++ b/src/java/com/threerings/whirled/spot/data/SpotSceneModel.java
@@ -1,119 +1,79 @@
//
-// $Id: SpotSceneModel.java,v 1.8 2002/07/23 05:54:52 mdb Exp $
+// $Id: SpotSceneModel.java,v 1.9 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.data;
-import com.samskivert.util.StringUtil;
+import com.samskivert.util.ArrayUtil;
+import com.samskivert.util.ListUtil;
+
+import com.threerings.io.SimpleStreamableObject;
+import com.threerings.util.DirectionUtil;
+
+import com.threerings.whirled.data.AuxModel;
import com.threerings.whirled.data.SceneModel;
/**
* The spot scene model extends the standard scene model with information
- * on locations, clusters and portals. Locations (and by extension,
- * portals) are referenced by an identifier, unique within the scene and
- * unchanging, so that portals can stably reference the target location in
- * the scene to which they connect. Clusters are tracked by index rather
- * than unique identifier, but only exist as an attribute of locations (a
- * location belongs to zero or one clusters).
+ * on portals. Portals are referenced by an identifier, unique within the
+ * scene and unchanging, so that portals can stably reference the target
+ * portal in the scene to which they connect.
*/
-public class SpotSceneModel extends SceneModel
+public class SpotSceneModel extends SimpleStreamableObject
+ implements AuxModel
{
- /** The unique (within the scope of this scene) identifier of each
- * location in this scene (including portals). */
- public int[] locationIds;
+ /** An array containing all portals in this scene. */
+ public Portal[] portals = new Portal[0];
- /** The x coordinates of the locations in this scene (including
- * portals). */
- public int[] locationX;
-
- /** The y coordinates of the locations in this scene (including
- * portals). */
- public int[] locationY;
-
- /** The orientations associated with the locations in this scene
- * (including portals). */
- public int[] locationOrients;
-
- /** The cluster index of each location in this scene, which can be 0
- * to indicate that the location is not a member of any cluster
- * (including portals, which should always be 0). */
- public int[] locationClusters;
-
- /** The location id of the default entrance to this scene. If a body
+ /** The portal id of the default entrance to this scene. If a body
* enters the scene without coming from another scene, this is the
- * location at which they would appear. */
- public int defaultEntranceId;
+ * portal at which they would appear. */
+ public int defaultEntranceId = -1;
- /** The location id of each portal in this scene. These must map, in
- * order, to the neighboring scene ids specified in {@link
- * #neighborIds}. The neighbor ids being the scene ids of the scenes
- * to which these portals take a body when "used". Additionally, these
- * must occur in the same order that the location ids appear in the
- * above array. */
- public int[] portalIds;
+ /**
+ * Adds a portal to this scene model.
+ */
+ public void addPortal (Portal portal)
+ {
+ portals = (Portal[])ArrayUtil.append(portals, portal);
+ }
- /** Contains the location ids of the entry location in the target
- * scene to which this scene's portals connect. Portals in this scene
- * connect to locations in other scenes as dictated by these
- * values. */
- public int[] targetLocIds;
+ /**
+ * Removes a portal from this model.
+ */
+ public void removePortal (Portal portal)
+ {
+ int pidx = ListUtil.indexOfEqual(portals, portal);
+ if (pidx != -1) {
+ portals = (Portal[])ArrayUtil.splice(portals, pidx, 1);
+ }
+ }
// documentation inherited
public Object clone ()
throws CloneNotSupportedException
{
SpotSceneModel model = (SpotSceneModel)super.clone();
- model.locationIds = (int[])locationIds.clone();
- model.locationX = (int[])locationX.clone();
- model.locationY = (int[])locationY.clone();
- model.locationOrients = (int[])locationOrients.clone();
- model.locationClusters = (int[])locationClusters.clone();
- model.portalIds = (int[])portalIds.clone();
- model.targetLocIds = (int[])targetLocIds.clone();
+ // clone our portals individually
+ model.portals = new Portal[portals.length];
+ for (int ii = 0, ll = portals.length; ii < ll; ii++) {
+ model.portals[ii] = (Portal)portals[ii].clone();
+ }
return model;
}
/**
- * Creates and returns a blank scene model.
+ * Locates and returns the {@link SpotSceneModel} among the auxiliary
+ * scene models associated with the supplied scene
+ * model. null is returned if no spot scene model could
+ * be found.
*/
- public static SpotSceneModel blankSpotSceneModel ()
+ public static SpotSceneModel getSceneModel (SceneModel model)
{
- SpotSceneModel model = new SpotSceneModel();
- populateBlankSpotSceneModel(model);
- return model;
- }
-
- /**
- * Populates a blank scene model with blank values.
- */
- protected static void populateBlankSpotSceneModel (SpotSceneModel model)
- {
- // populate our superclass fields
- populateBlankSceneModel(model);
-
- // now populate our fields
- model.locationIds = new int[0];
- model.locationX = new int[0];
- model.locationY = new int[0];
- model.locationOrients = new int[0];
- model.locationClusters = new int[0];
- model.defaultEntranceId = -1;
- model.portalIds = new int[0];
- model.targetLocIds = new int[0];
- }
-
- // documentation inherited
- protected void toString (StringBuffer buf)
- {
- super.toString(buf);
- buf.append(", locationIds=").append(StringUtil.toString(locationIds));
- buf.append(", locationX=").append(StringUtil.toString(locationX ));
- buf.append(", locationY=").append(StringUtil.toString(locationY));
- buf.append(", locationOrients=").
- append(StringUtil.toString(locationOrients));
- buf.append(", locationClusters=").
- append(StringUtil.toString(locationClusters));
- buf.append(", defaultEntranceId=").append(defaultEntranceId);
- buf.append(", portalIds=").append(StringUtil.toString(portalIds));
- buf.append(", targetLocIds=").append(StringUtil.toString(targetLocIds));
+ for (int ii = 0; ii < model.auxModels.length; ii++) {
+ if (model.auxModels[ii] instanceof SpotSceneModel) {
+ return (SpotSceneModel)model.auxModels[ii];
+ }
+ }
+ return null;
}
}
diff --git a/src/java/com/threerings/whirled/spot/data/SpotSceneObject.dobj b/src/java/com/threerings/whirled/spot/data/SpotSceneObject.dobj
new file mode 100644
index 000000000..637d2fbc6
--- /dev/null
+++ b/src/java/com/threerings/whirled/spot/data/SpotSceneObject.dobj
@@ -0,0 +1,17 @@
+//
+// $Id: SpotSceneObject.dobj,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.spot.data;
+
+import com.threerings.presents.dobj.DSet;
+import com.threerings.whirled.data.SceneObject;
+
+/**
+ * Extends the {@link SceneObject} with information specific to spots.
+ */
+public class SpotSceneObject extends SceneObject
+{
+ /** A distributed set containing {@link SceneLocation} records for all
+ * occupants of this scene. */
+ public DSet occupantLocs = new DSet();
+}
diff --git a/src/java/com/threerings/whirled/spot/data/SpotSceneObject.java b/src/java/com/threerings/whirled/spot/data/SpotSceneObject.java
new file mode 100644
index 000000000..81a5f4e9e
--- /dev/null
+++ b/src/java/com/threerings/whirled/spot/data/SpotSceneObject.java
@@ -0,0 +1,66 @@
+//
+// $Id: SpotSceneObject.java,v 1.1 2003/02/12 07:23:31 mdb Exp $
+
+package com.threerings.whirled.spot.data;
+
+import com.threerings.presents.dobj.DSet;
+import com.threerings.whirled.data.SceneObject;
+
+/**
+ * Extends the {@link SceneObject} with information specific to spots.
+ */
+public class SpotSceneObject extends SceneObject
+{
+ /** The field name of the occupantLocs field. */
+ public static final String OCCUPANT_LOCS = "occupantLocs";
+
+ /** A distributed set containing {@link SceneLocation} records for all
+ * occupants of this scene. */
+ public DSet occupantLocs = new DSet();
+
+ /**
+ * Requests that the specified entry be added to the
+ * occupantLocs set. The set will not change until the event is
+ * actually propagated through the system.
+ */
+ public void addToOccupantLocs (DSet.Entry elem)
+ {
+ requestEntryAdd(OCCUPANT_LOCS, elem);
+ }
+
+ /**
+ * Requests that the entry matching the supplied key be removed from
+ * the occupantLocs set. The set will not change until the
+ * event is actually propagated through the system.
+ */
+ public void removeFromOccupantLocs (Object key)
+ {
+ requestEntryRemove(OCCUPANT_LOCS, key);
+ }
+
+ /**
+ * Requests that the specified entry be updated in the
+ * occupantLocs set. The set will not change until the event is
+ * actually propagated through the system.
+ */
+ public void updateOccupantLocs (DSet.Entry elem)
+ {
+ requestEntryUpdate(OCCUPANT_LOCS, elem);
+ }
+
+ /**
+ * Requests that the occupantLocs field be set to the
+ * specified value. Generally one only adds, updates and removes
+ * entries of a distributed set, but certain situations call for a
+ * complete replacement of the set value. The local value will be
+ * updated immediately and an event will be propagated through the
+ * system to notify all listeners that the attribute did
+ * change. Proxied copies of this object (on clients) will apply the
+ * value change when they received the attribute changed notification.
+ */
+ public void setOccupantLocs (DSet occupantLocs)
+ {
+ this.occupantLocs = occupantLocs;
+ requestAttributeChange(OCCUPANT_LOCS, occupantLocs);
+ }
+}
diff --git a/src/java/com/threerings/whirled/spot/server/RuntimeSpotScene.java b/src/java/com/threerings/whirled/spot/server/RuntimeSpotScene.java
deleted file mode 100644
index 1ffc4ebe2..000000000
--- a/src/java/com/threerings/whirled/spot/server/RuntimeSpotScene.java
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// $Id: RuntimeSpotScene.java,v 1.5 2003/02/04 03:12:07 mdb Exp $
-
-package com.threerings.whirled.spot.server;
-
-import com.threerings.whirled.server.RuntimeScene;
-import com.threerings.whirled.spot.data.SpotSceneModel;
-
-/**
- * Makes available the spot scene information that the server needs to
- * manage requests to move from location to location, to enter and exit a
- * scene at a location and to manage speaking among bodies that occupy the
- * same clusters.
- */
-public interface RuntimeSpotScene extends RuntimeScene
-{
- /**
- * Returns the number of locations (and portals) in this scene.
- */
- public int getLocationCount ();
-
- /**
- * Returns the location id of the location at the specified index.
- */
- public int getLocationId (int locidx);
-
- /**
- * Returns the index of the specified location id.
- */
- public int getLocationIndex (int locationId);
-
- /**
- * Returns the total number of clusters in this scene.
- */
- public int getClusterCount ();
-
- /**
- * Returns the cluster index associated with the specified location
- * index or -1 if the location at that index is not associated with a
- * cluster.
- */
- public int getClusterIndex (int locationIdx);
-
- /**
- * Returns the location id of the default entrance to this scene. If a
- * body enters the scene at logon time rather than entering from some
- * other scene, this is the location at which they would appear.
- */
- public int getDefaultEntranceId ();
-
- /**
- * Returns the target scene id associated with the specified portal
- * (identified by its location id) or -1 if the location id specified
- * is not a portal.
- */
- public int getTargetSceneId (int locationId);
-
- /**
- * Returns the target location id associated with the specified portal
- * (identified by its location id) or -1 if the location id specified
- * is not a portal.
- */
- public int getTargetLocationId (int locationId);
-
- /**
- * Adds a portal to this runtime scene, immediately making the
- * requisite modifications to the underlying scene model.
- *
- * @return the location id assigned to the newly created portal.
- */
- public int addPortal (int locX, int locY, int orient,
- int targetSceneId, int targetLocId);
-
- /**
- * Returns a reference to the underlying model.
- */
- public SpotSceneModel getModel ();
-}
diff --git a/src/java/com/threerings/whirled/spot/server/RuntimeSpotSceneImpl.java b/src/java/com/threerings/whirled/spot/server/RuntimeSpotSceneImpl.java
deleted file mode 100644
index d18940624..000000000
--- a/src/java/com/threerings/whirled/spot/server/RuntimeSpotSceneImpl.java
+++ /dev/null
@@ -1,158 +0,0 @@
-//
-// $Id: RuntimeSpotSceneImpl.java,v 1.7 2003/02/06 18:58:30 mdb Exp $
-
-package com.threerings.whirled.spot.server;
-
-import com.samskivert.util.ArrayUtil;
-import com.samskivert.util.IntListUtil;
-
-import com.threerings.crowd.data.PlaceConfig;
-import com.threerings.whirled.server.RuntimeSceneImpl;
-
-import com.threerings.whirled.spot.data.SpotSceneModel;
-
-/**
- * A basic implementation of the {@link RuntimeSpotScene} interface which
- * is used by default if no extended implementation is desired.
- */
-public class RuntimeSpotSceneImpl extends RuntimeSceneImpl
- implements RuntimeSpotScene
-{
- /**
- * Creates an instance that will obtain data from the supplied scene
- * model and place config.
- */
- public RuntimeSpotSceneImpl (SpotSceneModel model, PlaceConfig config)
- {
- super(model, config);
-
- // keep a casted reference to our scene model around
- _model = model;
-
- // determine the highest cluster index
- int lcount = _model.locationIds.length;
- for (int i = 0; i < lcount; i++) {
- int cidx = _model.locationClusters[i];
- if (cidx > _clusterCount) {
- _clusterCount = cidx;
- }
- }
- // now increment by one to get the count rather than the highest
- // cluster index
- _clusterCount++;
- }
-
- // documentation inherited
- public int getLocationCount ()
- {
- return _model.locationIds.length;
- }
-
- // documentation inherited
- public int getLocationId (int locidx)
- {
- return _model.locationIds[locidx];
- }
-
- // documentation inherited
- public int getLocationIndex (int locationId)
- {
- return IntListUtil.indexOf(_model.locationIds, locationId);
- }
-
- // documentation inherited
- public int getClusterCount ()
- {
- return _clusterCount;
- }
-
- // documentation inherited
- public int getClusterIndex (int locationIdx)
- {
- return _model.locationClusters[locationIdx];
- }
-
- // documentation inherited
- public int getDefaultEntranceId ()
- {
- return _model.defaultEntranceId;
- }
-
- // documentation inherited
- public int getTargetSceneId (int locationId)
- {
- int pidx = getPortalIndex(locationId);
- return (pidx == -1) ? -1 : _model.neighborIds[pidx];
- }
-
- // documentation inherited
- public int getTargetLocationId (int locationId)
- {
- int pidx = getPortalIndex(locationId);
- return (pidx == -1) ? -1 : _model.targetLocIds[pidx];
- }
-
- // make or may not make it into the public interface
- public int addLocation (int locX, int locY, int orient, int cluster)
- {
- // compute the highest location id already used in the scene and
- // add one to it for our new location id
- int nlocid = Math.max(
- IntListUtil.getMaxValue(_model.locationIds), 0) + 1;
-
- // expand the necessary arrays
- _model.locationIds = ArrayUtil.append(_model.locationIds, nlocid);
- _model.locationX = ArrayUtil.append(_model.locationX, locX);
- _model.locationY = ArrayUtil.append(_model.locationY, locY);
- _model.locationOrients =
- ArrayUtil.append(_model.locationOrients, orient);
- _model.locationClusters =
- ArrayUtil.append(_model.locationOrients, cluster);
-
- return nlocid;
- }
-
- // documentation inherited from interface
- public int addPortal (int locX, int locY, int orient,
- int targetSceneId, int targetLocId)
- {
- // add the location information for this portal
- int nlocid = addLocation(locX, locY, orient, 0);
-
- // expand the necessary portal arrays
- _model.neighborIds =
- ArrayUtil.append(_model.neighborIds, targetSceneId);
- _model.portalIds = ArrayUtil.append(_model.portalIds, nlocid);
- _model.targetLocIds =
- ArrayUtil.append(_model.targetLocIds, targetLocId);
-
- return nlocid;
- }
-
- // documentation inherited from interface
- public SpotSceneModel getModel ()
- {
- return _model;
- }
-
- /**
- * Returns the index of the specified portal in the model's internal
- * portal arrays.
- */
- protected int getPortalIndex (int portalId)
- {
- int pcount = _model.portalIds.length;
- for (int i = 0; i < pcount; i++) {
- if (_model.portalIds[i] == portalId) {
- return i;
- }
- }
- return -1;
- }
-
- /** A casted reference to our scene model. */
- protected SpotSceneModel _model;
-
- /** The total number of clusters in this scene. */
- protected int _clusterCount = -1;
-}
diff --git a/src/java/com/threerings/whirled/spot/server/SpotDispatcher.java b/src/java/com/threerings/whirled/spot/server/SpotDispatcher.java
index 5a9bb7e88..135975cf5 100644
--- a/src/java/com/threerings/whirled/spot/server/SpotDispatcher.java
+++ b/src/java/com/threerings/whirled/spot/server/SpotDispatcher.java
@@ -1,5 +1,5 @@
//
-// $Id: SpotDispatcher.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
+// $Id: SpotDispatcher.java,v 1.3 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.server;
@@ -12,14 +12,11 @@ import com.threerings.whirled.client.SceneService.SceneMoveListener;
import com.threerings.whirled.data.SceneMarshaller.SceneMoveMarshaller;
import com.threerings.whirled.spot.client.SpotService;
import com.threerings.whirled.spot.client.SpotService.ChangeLocListener;
+import com.threerings.whirled.spot.data.Location;
import com.threerings.whirled.spot.data.SpotMarshaller;
/**
* Dispatches requests to the {@link SpotProvider}.
- *
- *
- * $Id: SpotDispatcher.java,v 1.2 2002/08/20 19:38:15 mdb Exp $
- *
*/
public class SpotDispatcher extends InvocationDispatcher
{
@@ -47,21 +44,21 @@ public class SpotDispatcher extends InvocationDispatcher
case SpotMarshaller.TRAVERSE_PORTAL:
((SpotProvider)provider).traversePortal(
source,
- ((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), ((Integer)args[2]).intValue(), (SceneMoveListener)args[3]
+ ((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (SceneMoveListener)args[2]
);
return;
case SpotMarshaller.CHANGE_LOC:
((SpotProvider)provider).changeLoc(
source,
- ((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (ChangeLocListener)args[2]
+ (Location)args[0], ((Integer)args[1]).intValue(), (ChangeLocListener)args[2]
);
return;
case SpotMarshaller.CLUSTER_SPEAK:
((SpotProvider)provider).clusterSpeak(
source,
- ((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (String)args[2], ((Byte)args[3]).byteValue()
+ (String)args[0], ((Byte)args[1]).byteValue()
);
return;
@@ -69,4 +66,6 @@ public class SpotDispatcher extends InvocationDispatcher
super.dispatchRequest(source, methodId, args);
}
}
+
+ // Generated on 10:09:04 02/05/03.
}
diff --git a/src/java/com/threerings/whirled/spot/server/SpotProvider.java b/src/java/com/threerings/whirled/spot/server/SpotProvider.java
index 1856a7e3f..024e3b30c 100644
--- a/src/java/com/threerings/whirled/spot/server/SpotProvider.java
+++ b/src/java/com/threerings/whirled/spot/server/SpotProvider.java
@@ -1,8 +1,10 @@
//
-// $Id: SpotProvider.java,v 1.14 2002/12/14 01:51:00 mdb Exp $
+// $Id: SpotProvider.java,v 1.15 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.server;
+import com.samskivert.util.StringUtil;
+
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.dobj.RootDObjectManager;
import com.threerings.presents.server.InvocationException;
@@ -16,13 +18,16 @@ import com.threerings.crowd.server.PlaceRegistry;
import com.threerings.whirled.client.SceneService.SceneMoveListener;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.ScenedBodyObject;
import com.threerings.whirled.server.SceneManager;
import com.threerings.whirled.server.SceneRegistry;
import com.threerings.whirled.spot.Log;
import com.threerings.whirled.spot.client.SpotService.ChangeLocListener;
+import com.threerings.whirled.spot.data.Location;
+import com.threerings.whirled.spot.data.Portal;
import com.threerings.whirled.spot.data.SpotCodes;
-import com.threerings.whirled.spot.data.SpotOccupantInfo;
+import com.threerings.whirled.spot.data.SpotScene;
/**
* Provides the server-side implementation of the spot services.
@@ -44,24 +49,18 @@ public class SpotProvider
}
/**
- * Processes a request from a client to traverse a portal.
- *
- * @param source the body object of the client making the request.
- * @param sceneId the source scene id.
- * @param portalId the portal in the source scene that is being
- * traversed.
- * @param sceneVer the version of the destination scene data that the
- * client has cached.
- * @param listener the entity to which we communicate our response.
+ * Processes a {@link SpotService#traversePortal} request.
*/
- public void traversePortal (ClientObject caller, int sceneId, int portalId,
- int sceneVer, SceneMoveListener listener)
+ public void traversePortal (ClientObject caller, int portalId,
+ int destSceneVer, SceneMoveListener listener)
throws InvocationException
{
+ int sceneId = getCallerSceneId(caller);
+
// avoid cluttering up the method declaration with final keywords
final BodyObject fsource = (BodyObject)caller;
final int fportalId = portalId;
- final int fsceneVer = sceneVer;
+ final int fsceneVer = destSceneVer;
final SceneMoveListener flistener = listener;
// obtain the source scene
@@ -75,28 +74,26 @@ public class SpotProvider
}
// obtain the destination scene and location id
- RuntimeSpotScene rss = (RuntimeSpotScene)smgr.getScene();
- int destSceneId = rss.getTargetSceneId(portalId);
- final int destLocId = rss.getTargetLocationId(portalId);
+ SpotScene rss = (SpotScene)smgr.getScene();
+ final Portal fdest = rss.getPortal(portalId);
// make sure this portal has valid info
- if (destSceneId == -1) {
- Log.warning("Traverse portal provided with invalid portal " +
- "[user=" + fsource.who() + ", sceneId=" + sceneId +
- ", portalId=" + portalId +
- ", destSceneId=" + destSceneId + "].");
+ if (fdest == null || !fdest.isValid()) {
+ Log.warning("Traverse portal with invalid portal " +
+ "[user=" + fsource.who() + ", scene=" + smgr.where() +
+ ", pid=" + portalId + ", portal=" + fdest +
+ ", portals=" + StringUtil.toString(rss.getPortals()) +
+ "].");
throw new InvocationException(NO_SUCH_PORTAL);
}
- // create a callback object that will handle the resolution or
- // failed resolution of the scene
+ // resolve their destination scene
SceneRegistry.ResolutionListener rl =
new SceneRegistry.ResolutionListener() {
public void sceneWasResolved (SceneManager scmgr) {
SpotSceneManager sscmgr = (SpotSceneManager)scmgr;
finishTraversePortalRequest(
- fsource, sscmgr, fsceneVer, fportalId, destLocId,
- flistener);
+ fsource, sscmgr, fsceneVer, fdest, flistener);
}
public void sceneFailedToResolve (
@@ -108,10 +105,7 @@ public class SpotProvider
flistener.requestFailed(NO_SUCH_PLACE);
}
};
-
- // make sure the scene they are headed to is actually loaded into
- // the server
- _screg.resolveScene(destSceneId, rl);
+ _screg.resolveScene(fdest.targetSceneId, rl);
}
/**
@@ -120,11 +114,10 @@ public class SpotProvider
*/
protected void finishTraversePortalRequest (
BodyObject source, SpotSceneManager scmgr, int sceneVer,
- int exitPortalId, int destLocId, SceneMoveListener listener)
+ Portal dest, SceneMoveListener listener)
{
// let the destination scene manager know that we're coming in
- int bodyOid = source.getOid();
- scmgr.mapEnteringBody(bodyOid, destLocId);
+ scmgr.mapEnteringBody(source, dest.targetPortalId);
try {
// move to the place object associated with this scene
@@ -133,17 +126,18 @@ public class SpotProvider
listener.requestFailed(sfe.getMessage());
// and let the destination scene manager know that we're no
// longer coming in
- scmgr.clearEnteringBody(bodyOid);
+ scmgr.clearEnteringBody(source);
}
}
/**
- * Processes a request from a client to move to a new location.
+ * Processes a {@link SpotService#changeLog} request.
*/
- public void changeLoc (ClientObject caller, int sceneId, int locationId,
+ public void changeLoc (ClientObject caller, Location loc, int cluster,
ChangeLocListener listener)
throws InvocationException
{
+ int sceneId = getCallerSceneId(caller);
BodyObject source = (BodyObject)caller;
// look up the scene manager for the specified scene
@@ -152,23 +146,25 @@ public class SpotProvider
if (smgr == null) {
Log.warning("User requested to change location in " +
"non-existent scene [user=" + source.who() +
- ", sceneId=" + sceneId +
- ", locId=" + locationId + "].");
+ ", sceneId=" + sceneId + ", loc=" + loc +"].");
throw new InvocationException(INTERNAL_ERROR);
}
- int locOid = smgr.handleChangeLocRequest(source, locationId);
- listener.changeLocSucceeded(locOid);
+ // pass the buck to yon scene manager
+ smgr.handleChangeLocRequest(source, loc, cluster);
+
+ // if that method finished, we're good to go
+ listener.changeLocSucceeded();
}
/**
* Handles request to generate a speak message in the specified cluster.
*/
- public void clusterSpeak (ClientObject caller, int sceneId, int locationId,
- String message, byte mode)
+ public void clusterSpeak (ClientObject caller, String message, byte mode)
+ throws InvocationException
{
BodyObject source = (BodyObject)caller;
- sendClusterChatMessage(sceneId, locationId, source.getOid(),
+ sendClusterChatMessage(getCallerSceneId(caller), source.getOid(),
source.username, null, message, mode);
}
@@ -181,7 +177,6 @@ public class SpotProvider
* message text) and with the supplied message content.
*
* @param sceneId the scene id in which to deliver the chat message.
- * @param locId the location whose cluster will be spoken to.
* @param speakerOid the body object id of the speaker (used to verify
* that they are in the cluster in question).
* @param speaker the username of the user that generated the message
@@ -192,24 +187,39 @@ public class SpotProvider
* @param message the text of the chat message.
*/
public void sendClusterChatMessage (
- int sceneId, int locId, int speakerOid, String speaker,
+ int sceneId, int speakerOid, String speaker,
String bundle, String message, byte mode)
{
// look up the scene manager for the specified scene
SpotSceneManager smgr = (SpotSceneManager)
_screg.getSceneManager(sceneId);
if (smgr == null) {
- Log.warning("User requested cluster chat in " +
- "non-existent scene [user=" + speaker +
- ", sceneId=" + sceneId + ", locId=" + locId +
+ Log.warning("User requested cluster chat in non-existent scene " +
+ "[user=" + speaker + ", sceneId=" + sceneId +
", message=" + message + "].");
+ return;
+ }
+ // pass this request on to the spot scene manager
+ smgr.handleClusterSpeakRequest(
+ speakerOid, speaker, bundle, message, mode);
+ }
+
+ /**
+ * Obtains the scene id occupied by the supplied caller.
+ *
+ * @exception InvocationException thrown if the caller does not
+ * implement {@link ScenedBodyObject}.
+ */
+ protected static int getCallerSceneId (ClientObject caller)
+ throws InvocationException
+ {
+ if (caller instanceof ScenedBodyObject) {
+ return ((ScenedBodyObject)caller).getSceneId();
} else {
- // pass this request on to the spot scene manager as it will
- // need to check that the location exists and that the speaker
- // occupies it and so on
- smgr.handleClusterSpeakRequest(
- speakerOid, speaker, locId, bundle, message, mode);
+ Log.warning("Can't get scene from non-scened caller " +
+ caller.who() + ".");
+ throw new InvocationException(INTERNAL_ERROR);
}
}
diff --git a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java
index 5ee8a3b9b..d81f8a60a 100644
--- a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java
+++ b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java
@@ -1,10 +1,13 @@
//
-// $Id: SpotSceneManager.java,v 1.24 2003/01/31 23:10:46 mdb Exp $
+// $Id: SpotSceneManager.java,v 1.25 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.spot.server;
+import java.util.Iterator;
+
+import com.samskivert.util.ArrayIntSet;
+import com.samskivert.util.HashIntMap;
import com.samskivert.util.IntIntMap;
-import com.samskivert.util.IntListUtil;
import com.samskivert.util.StringUtil;
import com.threerings.presents.dobj.DObject;
@@ -20,10 +23,14 @@ import com.threerings.whirled.server.SceneManager;
import com.threerings.whirled.spot.Log;
import com.threerings.whirled.spot.data.ClusterObject;
+import com.threerings.whirled.spot.data.ClusteredBodyObject;
+import com.threerings.whirled.spot.data.Location;
+import com.threerings.whirled.spot.data.Portal;
+import com.threerings.whirled.spot.data.SceneLocation;
import com.threerings.whirled.spot.data.SpotCodes;
-import com.threerings.whirled.spot.data.SpotOccupantInfo;
+import com.threerings.whirled.spot.data.SpotScene;
import com.threerings.whirled.spot.data.SpotSceneModel;
-import com.threerings.whirled.spot.util.SpotSceneUtil;
+import com.threerings.whirled.spot.data.SpotSceneObject;
/**
* Handles the movement of bodies between locations in the scene and
@@ -41,202 +48,207 @@ public class SpotSceneManager extends SceneManager
SpotSceneManager mgr = (SpotSceneManager)
CrowdServer.plreg.getPlaceManager(body.location);
if (mgr != null) {
- RuntimeSpotScene scene = (RuntimeSpotScene)mgr.getScene();
+ SpotScene scene = (SpotScene)mgr.getScene();
try {
- mgr.handleChangeLocRequest(body, scene.getDefaultEntranceId());
+ Location eloc = scene.getDefaultEntrance().getLocation();
+ mgr.handleChangeLocRequest(body, eloc, -1);
} catch (InvocationException ie) {
- Log.warning("Could not walk user to default portal " +
- "[error=" + ie + "].");
+ Log.warning("Could not move user to default portal " +
+ "[where=" + mgr.where() + ", who=" + body.who() +
+ ", error=" + ie + "].");
}
}
}
/**
- * Prepares a mapping for an entering body, indicating that they will
- * be entering at the specified location id. When the time comes to
- * prepare that body's occupant info, we will use the supplied
- * location id as their starting location.
+ * Assigns a starting location for an entering body. This will happen
+ * before the body is made to "occupy" the scene (defined by their
+ * having an occupant info record). So when they do finally occupy the
+ * scene, the client will know where to render them.
*/
- public void mapEnteringBody (int bodyOid, int locationId)
+ public void mapEnteringBody (BodyObject body, int portalId)
{
- _entering.put(bodyOid, locationId);
+ _enterers.put(body.getOid(), portalId);
}
/**
- * If scene entry fails, this can be called to undo a scene entry
- * mapping.
+ * Called if a body failed to enter our scene after we assigned them
+ * an entering position.
*/
- public void clearEnteringBody (int bodyOid)
+ public void clearEnteringBody (BodyObject body)
{
- _entering.remove(bodyOid);
+ _enterers.remove(body.getOid());
}
- /**
- * Returns the locationId of an unoccupied location in this scene
- * (portals are not included when selecting). If no locations are
- * unoccupied, this method returns -1. This will mark the location as
- * pending so that subsequent calls to
- * getUnoccupiedLocation() do not return the previously
- * returned location as unoccupied, giving the caller a chance to
- * actually occupy the location. However, if another user moves to
- * that location bewteen the call to this method and the caller's own
- * request to move to the location, the caller's move request will
- * fail.
- */
- public int getUnoccupiedLocation (boolean preferClusters)
+ // documentation inherited
+ protected void didStartup ()
{
- int locId = SpotSceneUtil.getUnoccupiedLocation(
- _sscene.getModel(), _locationOccs, preferClusters);
- if (locId != -1) {
- // mark the location as pending
-// Log.info("Earmarked location [scene=" + where() +
-// ", locId=" + locId + "].");
- _locationOccs[_sscene.getLocationIndex(locId)] = -1;
- }
- return locId;
- }
+ // get a casted reference to our place object (we need to do this
+ // before calling super.didStartup() because that will call
+ // sceneManagerDidResolve() which may start letting people into
+ // the scene)
+ _ssobj = (SpotSceneObject)_plobj;
- /**
- * Returns true if the location in question is occupied by another
- * body (or reserved for someone who's on their way).
- */
- public boolean isLocationOccupied (int locId)
- {
- return (_locationOccs[_sscene.getLocationIndex(locId)] != 0);
+ super.didStartup();
}
// documentation inherited
protected void gotSceneData ()
{
+ super.gotSceneData();
+
// keep a casted reference around to our scene
- _sscene = (RuntimeSpotScene)_scene;
-
- // now that we have our scene, we create chat objects for each of
- // the clusters in the scene
- _clusterObjs = new DObject[_sscene.getClusterCount()];
-
- // create a subscriber that will grab the oids when we hear back
- // about object creation
- Subscriber sub = new Subscriber() {
- public void objectAvailable (DObject object) {
- _clusterObjs[_index++] = object;
- }
-
- public void requestFailed (int oid, ObjectAccessException cause) {
- Log.warning("Failed to create cluster object " +
- "[where=" + where() + ", cluster=" + _index +
- ", oid=" + oid + ", cause=" + cause + "].");
- // skip to the next cluster in case others didn't fail
- _index++;
- }
-
- protected int _index = 0;
- };
-
- // now issue the object creation requests
- for (int i = 0; i < _clusterObjs.length; i++) {
- _omgr.createObject(ClusterObject.class, sub);
- }
-
- // create an array in which to track the occupants of each
- // location
- _locationOccs = new int[_sscene.getLocationCount()];
-
- _isPortal = new boolean[_sscene.getLocationCount()];
- SpotSceneModel model = _sscene.getModel();
- for (int ii=0; ii < model.locationIds.length; ii++) {
- _isPortal[ii] = IntListUtil.contains(model.portalIds,
- model.locationIds[ii]);
- }
+ _sscene = (SpotScene)_scene;
}
- /**
- * When a user is entering a scene, we populate their occupant info
- * with the location prepared by the portal traversal code or with the
- * default entrance for the scene if no preparation was done.
- */
+ // documentation inherited
+ protected void bodyLeft (int bodyOid)
+ {
+ super.bodyLeft(bodyOid);
+
+ // clear out their location information
+ _ssobj.removeFromOccupantLocs(new Integer(bodyOid));
+
+ // clear any cluster they may occupy
+ removeFromCluster(bodyOid);
+ }
+
+ // documentation inherited
protected void populateOccupantInfo (OccupantInfo info, BodyObject body)
{
super.populateOccupantInfo(info, body);
- // we have a table for tracking the locations of entering bodies
- // which is populated by the portal traversal code when a body
- // requests to enter our scene. if there's a mapped entrance
- // location for this body, use it, otherwise assume they're coming
- // in at the default entrance
- int entryLocId = _entering.remove(body.getOid());
- if (entryLocId == -1) {
- entryLocId = _sscene.getDefaultEntranceId();
+ // we don't actually populate their occupant info, but instead
+ // assign them their starting location in the scene
+ int portalId = _enterers.remove(body.getOid());
+ Portal entry;
+ if (portalId != -1) {
+ entry = _sscene.getPortal(portalId);
+ if (entry == null) {
+ Log.warning("Body mapped at invalid portal [where=" + where() +
+ ", who=" + body.who() +
+ ", portalId=" + portalId + "].");
+ entry = _sscene.getDefaultEntrance();
+ }
+ } else {
+ entry = _sscene.getDefaultEntrance();
}
- ((SpotOccupantInfo)info).locationId = entryLocId;
+
+// Log.info("Positioning entering body [who=" + body.who() +
+// ", where=" + entry.getOppLocation() + "].");
+
+ // create a scene location for them located on the entrance portal
+ // but facing the opposite direction
+ _ssobj.addToOccupantLocs(
+ new SceneLocation(entry.getOppLocation(), body.getOid()));
}
/**
* Called by the {@link SpotProvider} when we receive a request by a
* user to occupy a particular location.
*
- * @return the oid of the chat object associated with the cluster to
- * which this location belongs or -1 if the location is not part of a
- * cluster.
+ * @param source the body to be moved.
+ * @param loc the location to which to move the body.
+ * @param cluster if zero, a new cluster will be created and assigned
+ * to the moving user; if -1, the moving user will be removed from any
+ * cluster they currently occupy and not made to occupy a new cluster;
+ * if the bodyOid of another user, the moving user will be made to
+ * join the other user's cluster.
*
* @exception InvocationException thrown with a reason code explaining
* the location change failure if there is a problem processing the
* location change request.
*/
- protected int handleChangeLocRequest (BodyObject source, int locationId)
+ protected void handleChangeLocRequest (
+ BodyObject source, Location loc, int cluster)
throws InvocationException
{
- // make sure no one is already in the requested location
- int locidx = _sscene.getLocationIndex(locationId);
- if (locidx == -1) {
- Log.warning("Ignoring request to move to non-existent location " +
- "[where=" + where() + ", user=" + source.who() +
- ", locId=" + locationId + "].");
- throw new InvocationException(LOCATION_OCCUPIED);
-
- } else if (_locationOccs[locidx] > 0) {
- Log.info("Ignoring request to move to occupied location " +
- "[where=" + where() + ", user=" + source.who() +
- ", locId=" + locationId +
- ", occupantOid=" + _locationOccs[locidx] + "].");
- throw new InvocationException(LOCATION_OCCUPIED);
- }
-
- // make sure they have an occupant info object in the place
- int bodyOid = source.getOid();
- SpotOccupantInfo soi = (SpotOccupantInfo)getOccupantInfo(bodyOid);
- if (soi == null) {
- Log.warning("Aiya! Can't update non-existent occupant info " +
- "with new location [where=" + where() +
- ", body=" + source.who() + ":" + source.location +
- ", newLocId=" + locationId + "].");
+ // make sure they are in our scene
+ if (!_ssobj.occupants.contains(source.getOid())) {
+ Log.warning("Refusing change loc from non-scene occupant " +
+ "[where=" + where() + ", who=" + source.who() +
+ ", loc=" + loc + "].");
throw new InvocationException(INTERNAL_ERROR);
}
- // clear out any location they previously occupied
- if (soi.locationId > 0) {
- int oldlocidx = _sscene.getLocationIndex(soi.locationId);
- if (oldlocidx == -1) {
- Log.warning("Changing location for body that was " +
- "previously in an invalid location " +
- "[where=" + where() + ", info=" + soi + "].");
- } else {
- _locationOccs[oldlocidx] = 0;
- }
+ // update the user's location information in the scene which will
+ // indicate to the client that their avatar should be moved from
+ // its current position to their new position
+ SceneLocation sloc = new SceneLocation(loc, source.getOid());
+ if (!_ssobj.occupantLocs.contains(sloc)) {
+ // complain if they don't already have a location configured
+ Log.warning("Changing loc for occupant without previous loc " +
+ "[where=" + where() + ", who=" + source.who() +
+ ", nloc=" + loc + "].");
+ _ssobj.addToOccupantLocs(sloc);
+ } else {
+ _ssobj.updateOccupantLocs(sloc);
}
- // stick our new friend into that location, if it's not a portal
- if (!_isPortal[locidx]) {
- _locationOccs[locidx] = bodyOid;
+ // handle the cluster situation
+ switch (cluster) {
+ case 0:
+ createNewCluster(source);
+ break;
+ case -1:
+ removeFromCluster(source.getOid());
+ break;
+ default:
+ addToCluster(cluster, source);
+ break;
}
+ }
- // update the location and broadcast to the place
- soi.locationId = locationId;
- updateOccupantInfo(soi);
+ /**
+ * Creates a new cluster with the specified user being added to said
+ * cluster.
+ */
+ protected void createNewCluster (BodyObject creator)
+ {
+ // remove them from any previous cluster
+ removeFromCluster(creator.getOid());
- // figure out the cluster chat oid
- int clusterIdx = _sscene.getClusterIndex(locidx);
- return (clusterIdx == -1) ? -1 : _clusterObjs[clusterIdx].getOid();
+ // create a cluster record and map this user to it
+ ClusterRecord clrec = new ClusterRecord();
+ if (clrec.addBody(creator)) {
+ _clusters.put(creator.getOid(), clrec);
+ }
+ // if we failed to add the creator, the cluster record will
+ // quietly off itself when it's done subscribing to its object
+ }
+
+ /**
+ * Adds the specified user to the cluster occupied by the specified
+ * other user.
+ */
+ protected void addToCluster (int memberOid, BodyObject joiner)
+ {
+ ClusterRecord clrec = (ClusterRecord)_clusters.get(memberOid);
+ if (clrec == null) {
+ // this isn't completely impossible as the last user might
+ // leave a cluster just as another user is entering it, but
+ // before the entering user's client was informed that the
+ // cluster went away
+ Log.info("Can't add user to non-existent cluster; " +
+ "creating a new one just for them " +
+ "[memberOid=" + memberOid +
+ ", joiner=" + joiner.who() + "].");
+ clrec = new ClusterRecord();
+ }
+ if (clrec.addBody(joiner)) {
+ _clusters.put(joiner.getOid(), clrec);
+ }
+ }
+
+ /**
+ * Removes the specified user from any cluster they occupy.
+ */
+ protected void removeFromCluster (int bodyOid)
+ {
+ ClusterRecord clrec = (ClusterRecord)_clusters.remove(bodyOid);
+ if (clrec != null) {
+ clrec.removeBody(bodyOid);
+ }
}
/**
@@ -244,99 +256,123 @@ public class SpotSceneManager extends SceneManager
* request.
*/
protected void handleClusterSpeakRequest (
- int sourceOid, String source, int locationId,
- String bundle, String message, byte mode)
+ int sourceOid, String source, String bundle, String message, byte mode)
{
- int locIdx = _sscene.getLocationIndex(locationId);
-
- // make sure this user occupies the specified location
- int locOccId = (locIdx == -1) ? -1 : _locationOccs[locIdx];
- if (locOccId != sourceOid) {
- Log.warning("User not in specified location for CCREQ " +
+ ClusterRecord clrec = (ClusterRecord)_clusters.get(sourceOid);
+ if (clrec == null) {
+ Log.warning("Non-clustered user requested cluster speak " +
"[where=" + where() + ", chatter=" + source +
- " (" + sourceOid + "), locId=" + locationId +
- ", locIdx=" + locIdx +
- ", locOccs=" + StringUtil.toString(_locationOccs) +
- ", message=" + message + "].");
- return;
+ " (" + sourceOid + "), msg=" + message + "].");
+ } else {
+ SpeakProvider.sendSpeak(clrec.getClusterObject(),
+ source, bundle, message, mode);
}
-
- // make sure there's a cluster associated with this location
- int clusterIndex = _sscene.getClusterIndex(locIdx);
- if (clusterIndex == -1) {
- Log.warning("User in clusterless location sent CCREQ " +
- "[where=" + where() + ", chatter=" + source +
- " (" + sourceOid + "), locId=" + locationId +
- ", message=" + message + "].");
- return;
- }
-
- DObject clusterObj = _clusterObjs[clusterIndex];
- if (clusterObj == null) {
- Log.warning("Have no cluster object for CCREQ " +
- "[where=" + where() + ", cidx=" + clusterIndex +
- ", chatter=" + source + " (" + sourceOid +
- "), message=" + message + "].");
- return;
- }
-
- // all is well, generate a chat notification
- SpeakProvider.sendSpeak(clusterObj, source, bundle, message, mode);
}
/**
- * @return true if the specified user is in the scene and
- * in a valid location (not on a portal).
+ * Used to manage clusters which are groups of users that can chat to
+ * one another.
*/
- protected boolean inValidLocation (BodyObject body)
+ protected static class ClusterRecord extends HashIntMap
+ implements Subscriber
{
- int bodyOid = body.getOid();
- for (int ii=0; ii < _locationOccs.length; ii++) {
- if (_locationOccs[ii] == bodyOid) {
+ public ClusterRecord ()
+ {
+ CrowdServer.omgr.createObject(ClusterObject.class, this);
+ }
+
+ public boolean addBody (BodyObject body)
+ {
+ if (body instanceof ClusteredBodyObject) {
+ if (_clobj != null) {
+ ((ClusteredBodyObject)body).setClusterOid(_clobj.getOid());
+ }
+ put(body.getOid(), body);
+ _clobj.addToOccupants(body.getOid());
return true;
+
+ } else {
+ Log.warning("Refusing to add non-clustered body to cluster " +
+ "[cloid=" + _clobj.getOid() +
+ ", size=" + size() + ", who=" + body.who() + "].");
+ return false;
}
}
- return false;
- }
- /**
- * When an occupant leaves the room, we want to clear out any location
- * they may have occupied.
- */
- protected void bodyLeft (int bodyOid)
- {
- super.bodyLeft(bodyOid);
+ public void removeBody (int bodyOid)
+ {
+ ClusteredBodyObject body = (ClusteredBodyObject)remove(bodyOid);
+ if (body == null) {
+ Log.warning("Requested to remove unknown body from cluster " +
+ "[cloid=" + _clobj.getOid() +
+ ", size=" + size() + ", who=" + bodyOid + "].");
+ } else {
+ body.setClusterOid(-1);
+ _clobj.removeFromOccupants(bodyOid);
+ }
- for (int i = 0; i < _locationOccs.length; i++) {
- if (_locationOccs[i] == bodyOid) {
- _locationOccs[i] = 0;
- break;
+ // if we've removed our last body; stick a fork in ourselves
+ if (size() == 0) {
+ destroy();
}
}
+
+ public ClusterObject getClusterObject ()
+ {
+ return _clobj;
+ }
+
+ public void objectAvailable (DObject object)
+ {
+ // keep this feller around
+ _clobj = (ClusterObject)object;
+
+ // let any mapped users know about our cluster
+ Iterator iter = values().iterator();
+ while (iter.hasNext()) {
+ ClusteredBodyObject body = (ClusteredBodyObject)iter.next();
+ body.setClusterOid(_clobj.getOid());
+ }
+
+ // if we didn't manage to add our creating user when we first
+ // started up, there's no point in our sticking around
+ if (size() == 0) {
+ destroy();
+ }
+ }
+
+ public void requestFailed (int oid, ObjectAccessException cause)
+ {
+ Log.warning("Aiya! Failed to create cluster object " +
+ "[cause=" + cause + ", penders=" + size() + "].");
+
+ // let any mapped users know that we're hosed
+ Iterator iter = values().iterator();
+ while (iter.hasNext()) {
+ ClusteredBodyObject body = (ClusteredBodyObject)iter.next();
+ body.setClusterOid(-1);
+ }
+ }
+
+ protected void destroy ()
+ {
+ Log.info("Cluster empty, going away " +
+ "[cloid=" + _clobj.getOid() + "].");
+ CrowdServer.omgr.destroyObject(_clobj.getOid());
+ }
+
+ protected ClusterObject _clobj;
}
- /**
- * We need our own extended occupant info to keep track of what
- * location each occupant occupies.
- */
- protected Class getOccupantInfoClass ()
- {
- return SpotOccupantInfo.class;
- }
+ /** A casted reference to our place object. */
+ protected SpotSceneObject _ssobj;
- /** A casted reference to our runtime scene instance. */
- protected RuntimeSpotScene _sscene;
+ /** A casted reference to our scene instance. */
+ protected SpotScene _sscene;
- /** Our cluster chat objects. */
- protected DObject[] _clusterObjs;
+ /** Records with information on all clusters in this scene. */
+ protected HashIntMap _clusters = new HashIntMap();
- /** Oids of the bodies that occupy each of our locations. */
- protected int[] _locationOccs;
-
- /** Tracks if each location is a portal. */
- protected boolean[] _isPortal;
-
- /** A table of mappings from body oids to entry location ids for
- * bodies that are entering our scene. */
- protected IntIntMap _entering = new IntIntMap();
+ /** A mapping of entering bodies to portal ids. */
+ protected IntIntMap _enterers = new IntIntMap();
}
diff --git a/src/java/com/threerings/whirled/spot/tools/EditablePortal.java b/src/java/com/threerings/whirled/spot/tools/EditablePortal.java
index 4c78371af..d5d0bd722 100644
--- a/src/java/com/threerings/whirled/spot/tools/EditablePortal.java
+++ b/src/java/com/threerings/whirled/spot/tools/EditablePortal.java
@@ -1,7 +1,7 @@
//
-// $Id: EditablePortal.java,v 1.2 2001/12/05 03:38:09 mdb Exp $
+// $Id: EditablePortal.java,v 1.3 2003/02/12 07:23:31 mdb Exp $
-package com.threerings.whirled.tools.spot;
+package com.threerings.whirled.spot.tools;
import com.threerings.whirled.spot.data.Portal;
@@ -21,13 +21,4 @@ public class EditablePortal extends Portal
/** The human-readable name of the portal to which this portal links
* in its target scene. */
public String targetPortalName;
-
- // documentation inherited
- protected void toString (StringBuffer buf)
- {
- super.toString(buf);
- buf.append(", name=").append(name);
- buf.append(", targetScene=").append(targetSceneName);
- buf.append(", targetPortal=").append(targetPortalName);
- }
}
diff --git a/src/java/com/threerings/whirled/spot/tools/EditableSpotScene.java b/src/java/com/threerings/whirled/spot/tools/EditableSpotScene.java
deleted file mode 100644
index 2a0301bd3..000000000
--- a/src/java/com/threerings/whirled/spot/tools/EditableSpotScene.java
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// $Id: EditableSpotScene.java,v 1.5 2001/12/05 09:20:10 mdb Exp $
-
-package com.threerings.whirled.tools.spot;
-
-import com.threerings.whirled.tools.EditableScene;
-
-import com.threerings.whirled.spot.client.DisplaySpotScene;
-import com.threerings.whirled.spot.data.Location;
-import com.threerings.whirled.spot.data.Portal;
-import com.threerings.whirled.spot.data.SpotSceneModel;
-
-/**
- * The editable spot 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.
- *
- * @see EditableScene
- */
-public interface EditableSpotScene
- extends DisplaySpotScene, EditableScene
-{
- /**
- * Sets the location id of the default entrance to this scene.
- */
- public void setDefaultEntranceId (int defaultEntranceId);
-
- /**
- * Returns the next valid location id for this scene. Newly created
- * portals or locations should be assigned a new location id via this
- * method.
- */
- public int getNextLocationId ();
-
- /**
- * Adds a location to this scene.
- */
- public void addLocation (Location location);
-
- /**
- * Removes the specified location from the scene.
- */
- public void removeLocation (Location location);
-
- /**
- * Adds a portal to this scene (it should be added appropriately to
- * both the location and portal arrays).
- */
- public void addPortal (EditablePortal portal);
-
- /**
- * Removes a portal from this scene (it should be removed accordingly
- * from both the location and portal arrays).
- */
- public void removePortal (EditablePortal portal);
-
- /**
- * 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 EditableSpotSceneModel getSpotSceneModel ();
-}
diff --git a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneImpl.java b/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneImpl.java
deleted file mode 100644
index 8c89b6a6c..000000000
--- a/src/java/com/threerings/whirled/spot/tools/EditableSpotSceneImpl.java
+++ /dev/null
@@ -1,257 +0,0 @@
-//
-// $Id: EditableSpotSceneImpl.java,v 1.11 2003/01/31 23:10:46 mdb Exp $
-
-package com.threerings.whirled.tools.spot;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import com.threerings.crowd.data.PlaceConfig;
-import com.threerings.whirled.tools.EditableSceneModel;
-import com.threerings.whirled.tools.EditableSceneImpl;
-
-import com.threerings.whirled.spot.client.DisplaySpotSceneImpl;
-import com.threerings.whirled.spot.data.Location;
-import com.threerings.whirled.spot.data.Portal;
-import com.threerings.whirled.spot.data.SpotSceneModel;
-
-import com.threerings.whirled.spot.Log;
-
-/**
- * The editable spot 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.
- *
- * toString
- * data on to the string buffer.
- */
- protected void delegatesToString (StringBuffer buf)
- {
- buf.append(spotSceneModel);
- }
-
- /**
- * Derived classes override this to tack their toString
- * data on to the string buffer.
- */
- protected void toString (StringBuffer buf)
- {
- super.toString(buf);
- buf.append(", portalNames=").
- append(StringUtil.toString(portalNames));
- buf.append(", targetPortalNames=").
- append(StringUtil.toString(targetPortalNames));
- }
-
- /**
- * Creates and returns a blank scene model.
- */
- public static EditableSpotSceneModel blankSpotSceneModel ()
- {
- EditableSpotSceneModel model = new EditableSpotSceneModel();
- model.spotSceneModel = SpotSceneModel.blankSpotSceneModel();
- model.sceneModel = model.spotSceneModel;
- populateBlankSpotSceneModel(model);
- return model;
- }
-
- /**
- * Populates a blank scene model with blank values.
- */
- protected static void populateBlankSpotSceneModel (
- EditableSpotSceneModel model)
- {
- // populate our superclass fields
- populateBlankSceneModel(model);
-
- // now populate our fields
- model.portalNames = new String[0];
- model.targetPortalNames = new String[0];
- }
-}
diff --git a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParser.java b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParser.java
deleted file mode 100644
index c560e7df7..000000000
--- a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneParser.java
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// $Id: SpotSceneParser.java,v 1.1 2001/12/05 03:38:09 mdb Exp $
-
-package com.threerings.whirled.tools.spot.xml;
-
-import java.io.IOException;
-import java.io.FileInputStream;
-
-import org.xml.sax.SAXException;
-import org.apache.commons.digester.Digester;
-
-import com.threerings.whirled.tools.spot.EditableSpotScene;
-import com.threerings.whirled.tools.spot.EditableSpotSceneImpl;
-
-/**
- * A simple class for parsing an editable spot scene instance.
- */
-public class SpotSceneParser
-{
- /**
- * Constructs a scene parser that parses scenes with the specified XML
- * path prefix. See the {@link SpotSceneRuleSet#SpotSceneRuleSet}
- * documentation for more information.
- */
- public SpotSceneParser (String prefix)
- {
- // create and configure our digester
- _digester = new Digester();
- SpotSceneRuleSet set = new SpotSceneRuleSet();
- set.setPrefix(prefix);
- _digester.addRuleSet(set);
- _digester.addSetNext(prefix, "setScene",
- EditableSpotScene.class.getName());
- }
-
- /**
- * Parses the XML file at the specified path into an editable scene
- * instance.
- */
- public EditableSpotScene parseScene (String path)
- throws IOException, SAXException
- {
- _scene = null;
- _digester.push(this);
- _digester.parse(new FileInputStream(path));
- return _scene;
- }
-
- /**
- * Called by the parser once the scene is parsed.
- */
- public void setScene (EditableSpotScene scene)
- {
- _scene = scene;
- }
-
- protected Digester _digester;
- protected EditableSpotScene _scene;
-}
diff --git a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java
index e1a3ab7fb..f3477ca7c 100644
--- a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java
+++ b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java
@@ -1,54 +1,41 @@
//
-// $Id: SpotSceneRuleSet.java,v 1.3 2001/12/05 03:40:32 mdb Exp $
+// $Id: SpotSceneRuleSet.java,v 1.4 2003/02/12 07:23:31 mdb Exp $
-package com.threerings.whirled.tools.spot.xml;
-
-import org.apache.commons.digester.Digester;
-import org.apache.commons.digester.RuleSetBase;
+package com.threerings.whirled.spot.tools.xml;
import com.samskivert.xml.SetPropertyFieldsRule;
+import com.threerings.tools.xml.NestableRuleSet;
+import org.apache.commons.digester.Digester;
-import com.threerings.whirled.tools.xml.SceneRuleSet;
-
-import com.threerings.whirled.spot.data.Location;
-import com.threerings.whirled.tools.spot.EditablePortal;
-import com.threerings.whirled.tools.spot.EditableSpotScene;
-import com.threerings.whirled.tools.spot.EditableSpotSceneImpl;
+import com.threerings.whirled.spot.data.Portal;
+import com.threerings.whirled.spot.data.SpotSceneModel;
+import com.threerings.whirled.spot.tools.EditablePortal;
/**
- * Used to parse an {@link EditableSpotScene} from XML.
+ * Used to parse a {@link SpotSceneModel} from XML.
*/
-public class SpotSceneRuleSet extends SceneRuleSet
+public class SpotSceneRuleSet implements NestableRuleSet
{
- /**
- * Extends the scene rule set with the necessary rules to parse our
- * spot scene data.
- */
- public void addRuleInstances (Digester digester)
+ // documentation inherited from interface
+ public String getOuterElement ()
{
- super.addRuleInstances(digester);
+ return SpotSceneWriter.OUTER_ELEMENT;
+ }
- // create Location instances when we see toString
- * data on to the string buffer.
- */
- protected void delegatesToString (StringBuffer buf)
- {
- buf.append(sceneModel);
- }
-
- /**
- * Derived classes override this to tack their toString
- * data on to the string buffer.
- */
- protected void toString (StringBuffer buf)
- {
- buf.append(", neighborNames=").
- append(StringUtil.toString(neighborNames));
- }
-
- /**
- * Creates and returns a blank editable scene model.
- */
- public static EditableSceneModel blankSceneModel ()
- {
- EditableSceneModel model = new EditableSceneModel();
- model.sceneModel = SceneModel.blankSceneModel();
- populateBlankSceneModel(model);
- return model;
- }
-
- /**
- * Populates a blank editable scene model with blank values.
- */
- protected static void populateBlankSceneModel (EditableSceneModel model)
- {
- model.neighborNames = new ArrayList();
- }
-}
diff --git a/src/java/com/threerings/whirled/tools/xml/SceneParser.java b/src/java/com/threerings/whirled/tools/xml/SceneParser.java
index 35445ba07..2c5df0505 100644
--- a/src/java/com/threerings/whirled/tools/xml/SceneParser.java
+++ b/src/java/com/threerings/whirled/tools/xml/SceneParser.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneParser.java,v 1.1 2001/12/05 03:38:09 mdb Exp $
+// $Id: SceneParser.java,v 1.2 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.tools.xml;
@@ -9,8 +9,10 @@ import java.io.FileInputStream;
import org.xml.sax.SAXException;
import org.apache.commons.digester.Digester;
-import com.threerings.whirled.tools.EditableScene;
-import com.threerings.whirled.tools.EditableSceneImpl;
+import com.samskivert.util.StringUtil;
+import com.threerings.tools.xml.NestableRuleSet;
+import com.threerings.whirled.data.AuxModel;
+import com.threerings.whirled.data.SceneModel;
/**
* A simple class for parsing an editable scene instance.
@@ -19,40 +21,75 @@ public class SceneParser
{
/**
* Constructs a scene parser that parses scenes with the specified XML
- * path prefix. See the {@link SceneRuleSet#SceneRuleSet}
- * documentation for more information.
+ * path prefix.
*/
public SceneParser (String prefix)
{
// create and configure our digester
_digester = new Digester();
- SceneRuleSet set = new SceneRuleSet();
- set.setPrefix(prefix);
- _digester.addRuleSet(set);
- _digester.addSetNext(prefix, "setScene", EditableScene.class.getName());
+
+ // create our scene rule set
+ SceneRuleSet set = createSceneRuleSet();
+
+ // configure our top-level path prefix
+ if (StringUtil.blank(prefix)) {
+ _prefix = set.getOuterElement();
+ } else {
+ _prefix = prefix + "/" + set.getOuterElement();
+ }
+
+ // add the scene rules
+ set.addRuleInstances(_prefix, _digester);
+
+ // add a rule to grab the finished scene model
+ _digester.addSetNext(_prefix, "setScene", SceneModel.class.getName());
}
/**
- * Parses the XML file at the specified path into an editable scene
+ * Creates the rule set used to parse our scene.
+ */
+ protected SceneRuleSet createSceneRuleSet ()
+ {
+ return new SceneRuleSet();
+ }
+
+ /**
+ * Adds a {@link NestableRuleSet} for parsing auxiliary scene models.
+ */
+ public void registerAuxRuleSet (NestableRuleSet set)
+ {
+ // add their outer element to the prefix
+ String prefix = _prefix + "/" + set.getOuterElement();
+
+ // add the rules to generate the aux scene model
+ set.addRuleInstances(prefix, _digester);
+
+ // and add a rule to grab it
+ _digester.addSetNext(prefix, "addAuxModel", AuxModel.class.getName());
+ }
+
+ /**
+ * Parses the XML file at the specified path into a scene model
* instance.
*/
- public EditableScene parseScene (String path)
+ public SceneModel parseScene (String path)
throws IOException, SAXException
{
- _scene = null;
+ _model = null;
_digester.push(this);
_digester.parse(new FileInputStream(path));
- return _scene;
+ return _model;
}
/**
* Called by the parser once the scene is parsed.
*/
- public void setScene (EditableScene scene)
+ public void setScene (SceneModel model)
{
- _scene = scene;
+ _model = model;
}
+ protected String _prefix;
protected Digester _digester;
- protected EditableScene _scene;
+ protected SceneModel _model;
}
diff --git a/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java b/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java
index 2cf5164fa..6ee2ed930 100644
--- a/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java
+++ b/src/java/com/threerings/whirled/tools/xml/SceneRuleSet.java
@@ -1,63 +1,43 @@
//
-// $Id: SceneRuleSet.java,v 1.2 2001/12/05 03:38:09 mdb Exp $
+// $Id: SceneRuleSet.java,v 1.3 2003/02/12 07:23:31 mdb Exp $
package com.threerings.whirled.tools.xml;
import org.apache.commons.digester.Digester;
-import org.apache.commons.digester.RuleSetBase;
-import com.threerings.whirled.tools.EditableScene;
-import com.threerings.whirled.tools.EditableSceneImpl;
+import com.samskivert.util.StringUtil;
+import com.samskivert.xml.SetPropertyFieldsRule;
+
+import com.threerings.tools.xml.NestableRuleSet;
+import com.threerings.whirled.data.SceneModel;
/**
- * Used to parse an {@link EditableScene} from XML.
+ * Used to parse a {@link SceneModel} from XML.
*/
-public class SceneRuleSet extends RuleSetBase
+public class SceneRuleSet implements NestableRuleSet
{
- /**
- * Configures this scene rule set to match scenes with the supplied
- * prefix. For example, passing scene will match the
- * scene in the following XML file:
- *
- *
- * <scene name="Scene Name" version="3">
- * <neighbor>North Scene</neighbor>
- * <neighbor>West Scene</neighbor>
- * <!-- ... -->
- * </scene>
- *
- */
- public void setPrefix (String prefix)
+ // documentation inherited from interface
+ public String getOuterElement ()
{
- _prefix = prefix;
+ return SceneWriter.OUTER_ELEMENT;
}
- /**
- * Adds the necessary rules to the digester to parse our miso scene
- * data.
- */
- public void addRuleInstances (Digester digester)
+ // documentation inherited from interface
+ public void addRuleInstances (String prefix, Digester digester)
{
// this creates the appropriate instance when we encounter our tag
- digester.addObjectCreate(_prefix, getSceneClass().getName());
+ digester.addObjectCreate(prefix, getSceneClass().getName());
// set up rules to parse and set our fields
- digester.addSetProperties(_prefix);
- digester.addCallMethod(_prefix + "/neighbor", "addNeighbor", 0);
+ digester.addRule(prefix, new SetPropertyFieldsRule(digester));
}
/**
- * This indicates the class (which should implement {@link
- * EditableScene}) to be instantiated during the parsing process.
+ * This indicates the class (which should extend {@link SceneModel})
+ * to be instantiated during the parsing process.
*/
protected Class getSceneClass ()
{
- return EditableSceneImpl.class;
+ return SceneModel.class;
}
-
- /** The prefix at which me match our scenes. */
- protected String _prefix = DEFAULT_SCENE_PREFIX;
-
- /** The default prefix which matches <scene>. */
- protected static final String DEFAULT_SCENE_PREFIX = "scene";
}
diff --git a/src/java/com/threerings/whirled/tools/xml/SceneWriter.java b/src/java/com/threerings/whirled/tools/xml/SceneWriter.java
index 09149505e..ffbfb9109 100644
--- a/src/java/com/threerings/whirled/tools/xml/SceneWriter.java
+++ b/src/java/com/threerings/whirled/tools/xml/SceneWriter.java
@@ -1,11 +1,12 @@
//
-// $Id: SceneWriter.java,v 1.3 2003/01/30 19:16:50 mdb Exp $
+// $Id: SceneWriter.java,v 1.4 2003/02/12 07:23:32 mdb Exp $
package com.threerings.whirled.tools.xml;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.HashMap;
import java.util.Iterator;
import org.xml.sax.SAXException;
@@ -13,78 +14,92 @@ import org.xml.sax.helpers.AttributesImpl;
import com.megginson.sax.DataWriter;
import com.samskivert.util.StringUtil;
+import com.threerings.tools.xml.NestableWriter;
-import com.threerings.whirled.tools.EditableScene;
+import com.threerings.whirled.Log;
+import com.threerings.whirled.data.AuxModel;
+import com.threerings.whirled.data.SceneModel;
/**
- * Generates an XML representation of an {@link EditableScene}.
+ * Generates an XML representation of an {@link SceneModel}.
*/
public class SceneWriter
{
+ /** The outer element used to enclose our scene definition. */
+ public static final String OUTER_ELEMENT = "scene";
+
/**
- * Writes the data for the supplied {@link EditableScene} to the XML
- * writer supplied. The writer will already be configured with the
- * appropriate indentation level so that this writer can simply output
- * its elements and allow the calling code to determine where in the
- * greater scene description file the scene data should live.
+ * Registers a writer for writing auxiliary scene models of the
+ * supplied class.
*/
- public void writeScene (EditableScene scene, DataWriter writer)
- throws SAXException
+ public void registerAuxWriter (Class aclass, NestableWriter writer)
{
- AttributesImpl attrs = new AttributesImpl();
- addSceneAttributes(scene, attrs);
- writer.startElement("", sceneElementName(), "", attrs);
- writeSceneData(scene, writer);
- writer.endElement(sceneElementName());
+ _auxers.put(aclass, writer);
}
/**
- * Returns the name of the top-level element that we'll use when we
- * write out the scene (defaults to scene).
+ * Writes the supplied scene out to the specified file.
*/
- protected String sceneElementName ()
- {
- return "scene";
- }
-
- /**
- * Adds attributes to the top-level element before it gets written.
- */
- protected void addSceneAttributes (
- EditableScene scene, AttributesImpl attrs)
- {
- attrs.addAttribute("", "name", "", "", scene.getName());
- attrs.addAttribute("", "version", "", "",
- Integer.toString(scene.getVersion()));
- }
-
- /**
- * Writes just the scene data which is handy for derived classes which
- * may wish to add their own scene data to the scene output.
- */
- protected void writeSceneData (EditableScene scene, DataWriter writer)
- throws SAXException
- {
- Iterator iter = scene.getNeighborNames().iterator();
- while (iter.hasNext()) {
- writer.dataElement("neighbor", (String)iter.next());
- }
- }
-
- /**
- * Writes the supplied scene out to the specified file using the
- * supplied scene writer.
- */
- public static void writeScene (File out, SceneWriter writer,
- EditableScene scene)
+ public void writeScene (File out, SceneModel model)
throws IOException, SAXException
{
FileWriter fout = new FileWriter(out);
DataWriter dout = new DataWriter(fout);
dout.setIndentStep(2);
dout.startDocument();
- writer.writeScene(scene, dout);
+ writeSceneModel(model, dout);
dout.endDocument();
fout.close();
}
+
+ /**
+ * Writes the data for the supplied {@link SceneModel} to the XML data
+ * writer supplied. The writer should already be configured with the
+ * appropriate indentation level so that this writer can simply output
+ * its elements and allow the calling code to determine where in the
+ * greater scene description file the scene data should live.
+ */
+ public void writeSceneModel (SceneModel model, DataWriter writer)
+ throws SAXException
+ {
+ AttributesImpl attrs = new AttributesImpl();
+ addSceneAttributes(model, attrs);
+ writer.startElement("", OUTER_ELEMENT, "", attrs);
+ writeSceneData(model, writer);
+ writer.endElement(OUTER_ELEMENT);
+ }
+
+ /**
+ * Adds attributes to the top-level element before it gets written.
+ */
+ protected void addSceneAttributes (
+ SceneModel model, AttributesImpl attrs)
+ {
+ attrs.addAttribute("", "name", "", "", model.name);
+ attrs.addAttribute("", "version", "", "",
+ Integer.toString(model.version));
+ }
+
+ /**
+ * Writes just the scene data which is handy for derived classes which
+ * may wish to add their own scene data to the scene output.
+ */
+ protected void writeSceneData (SceneModel model, DataWriter writer)
+ throws SAXException
+ {
+ // write out our auxiliary scene models
+ for (int ii = 0; ii < model.auxModels.length; ii++) {
+ AuxModel amodel = model.auxModels[ii];
+ NestableWriter awriter = (NestableWriter)
+ _auxers.get(amodel.getClass());
+ if (awriter != null) {
+ awriter.write(amodel, writer);
+ } else {
+ Log.warning("No writer registered for auxiliary scene model " +
+ "[mclass=" + amodel.getClass() + "].");
+ }
+ }
+ }
+
+ protected HashMap _auxers = new HashMap();
}
diff --git a/src/java/com/threerings/whirled/util/SceneFactory.java b/src/java/com/threerings/whirled/util/SceneFactory.java
new file mode 100644
index 000000000..4a98e426f
--- /dev/null
+++ b/src/java/com/threerings/whirled/util/SceneFactory.java
@@ -0,0 +1,21 @@
+//
+// $Id: SceneFactory.java,v 1.1 2003/02/12 07:23:32 mdb Exp $
+
+package com.threerings.whirled.util;
+
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.whirled.data.Scene;
+import com.threerings.whirled.data.SceneModel;
+
+/**
+ * This is used by the Whirled services to obtain a {@link Scene}
+ * implementation given a scene model and associated data.
+ */
+public interface SceneFactory
+{
+ /**
+ * Creates a {@link Scene} implementation given the supplied scene
+ * model and place config.
+ */
+ public Scene createScene (SceneModel model, PlaceConfig config);
+}
diff --git a/src/java/com/threerings/whirled/util/UpdateList.java b/src/java/com/threerings/whirled/util/UpdateList.java
new file mode 100644
index 000000000..74198cf7b
--- /dev/null
+++ b/src/java/com/threerings/whirled/util/UpdateList.java
@@ -0,0 +1,89 @@
+//
+// $Id: UpdateList.java,v 1.1 2003/02/12 07:23:32 mdb Exp $
+
+package com.threerings.whirled.util;
+
+import java.util.ArrayList;
+
+import com.threerings.whirled.Log;
+import com.threerings.whirled.data.SceneUpdate;
+
+/**
+ * A list specialized for storing {@link SceneUpdate} objects.
+ */
+public class UpdateList
+{
+ public UpdateList ()
+ {
+ _updates = new ArrayList();
+ }
+
+ /**
+ * Adds an update to this list. The update must follow appropriately
+ * the chain of updates established by the updates already in the list
+ * (meaning it must operate on one version higher than the most recent
+ * update already in the list).
+ */
+ public void addUpdate (SceneUpdate update)
+ {
+ if (_minVersion == -1) {
+ // this is our first update, so we initialize our min version
+ _minVersion = update.getSceneVersion();
+
+ } else {
+ int gotVersion = update.getSceneVersion();
+ int expVersion = _minVersion + _updates.size();
+ if (gotVersion > expVersion) {
+ Log.warning("Update continuity broken, flushing list " +
+ "[got=" + update + ", expect=" + expVersion +
+ ", ucount=" + _updates.size() + "].");
+ // flush out our old updates and start anew from here
+ _updates.clear();
+ _minVersion = expVersion;
+
+ } else if (gotVersion < expVersion) {
+ // we somehow got an update that's older than updates we
+ // already have? wick wick wack
+ String errmsg = "Invalid update version " +
+ "[want=" + expVersion + ", got=" + update + "]";
+ throw new IllegalArgumentException(errmsg);
+ }
+ }
+ _updates.add(update);
+ }
+
+ /**
+ * Returns all of the updates that should be applied to a scene with
+ * the specified version to bring it up to date. null is
+ * returned if the scene's version is older than the oldest update in
+ * our list, in which case it cannot be brought up to date by applying
+ * updates from this list.
+ */
+ public SceneUpdate[] getUpdates (int fromVersion)
+ {
+ if (fromVersion < _minVersion) {
+ return null;
+ }
+
+ int offset = fromVersion - _minVersion;
+ int ucount = _updates.size() - offset;
+ SceneUpdate[] updates = new SceneUpdate[ucount];
+ for (int ii = 0; ii < ucount; ii++) {
+ updates[ii] = (SceneUpdate)_updates.get(ii+offset);
+ }
+ return updates;
+ }
+
+ /**
+ * Returns true if the supplied actual scene version is in accordance
+ * with the updates contained in this list.
+ */
+ public boolean validate (int sceneVersion)
+ {
+ return ((_minVersion == -1) || // we have no updates
+ (_minVersion + _updates.size() == sceneVersion));
+ }
+
+ protected ArrayList _updates;
+ protected int _minVersion = -1;
+}
diff --git a/src/java/com/threerings/whirled/zone/client/ZoneDirector.java b/src/java/com/threerings/whirled/zone/client/ZoneDirector.java
index 850f61aab..0d0598bc5 100644
--- a/src/java/com/threerings/whirled/zone/client/ZoneDirector.java
+++ b/src/java/com/threerings/whirled/zone/client/ZoneDirector.java
@@ -1,5 +1,5 @@
//
-// $Id: ZoneDirector.java,v 1.13 2003/01/18 22:45:16 mdb Exp $
+// $Id: ZoneDirector.java,v 1.14 2003/02/12 07:23:32 mdb Exp $
package com.threerings.whirled.zone.client;
@@ -14,6 +14,7 @@ import com.threerings.crowd.data.PlaceConfig;
import com.threerings.whirled.client.SceneDirector;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
import com.threerings.whirled.util.WhirledContext;
import com.threerings.whirled.zone.Log;
@@ -158,19 +159,38 @@ public class ZoneDirector extends BasicDirector
notifyObservers(summary);
}
+ /**
+ * Called in response to a successful {@link ZoneService#moveTo}
+ * request when our cached scene was out of date and the server
+ * determined that we needed some updates.
+ */
+ public void moveSucceededWithUpdates (
+ int placeId, PlaceConfig config, ZoneSummary summary,
+ SceneUpdate[] updates)
+ {
+ // keep track of the summary
+ _summary = summary;
+
+ // pass the rest off to the standard scene transition code
+ _scdir.moveSucceededWithUpdates(placeId, config, updates);
+
+ // and let the zone observers know what's up
+ notifyObservers(summary);
+ }
+
/**
* Called in response to a successful {@link ZoneService#moveTo}
* request when our cached scene was out of date and the server
* determined that we needed an updated copy.
*/
- public void moveSucceededPlusUpdate (
+ public void moveSucceededWithScene (
int placeId, PlaceConfig config, ZoneSummary summary, SceneModel model)
{
// keep track of the summary
_summary = summary;
// pass the rest off to the standard scene transition code
- _scdir.moveSucceededPlusUpdate(placeId, config, model);
+ _scdir.moveSucceededWithScene(placeId, config, model);
// and let the zone observers know what's up
notifyObservers(summary);
diff --git a/src/java/com/threerings/whirled/zone/client/ZoneService.java b/src/java/com/threerings/whirled/zone/client/ZoneService.java
index 613f9a41f..63f529363 100644
--- a/src/java/com/threerings/whirled/zone/client/ZoneService.java
+++ b/src/java/com/threerings/whirled/zone/client/ZoneService.java
@@ -1,5 +1,5 @@
//
-// $Id: ZoneService.java,v 1.6 2002/08/14 19:07:58 mdb Exp $
+// $Id: ZoneService.java,v 1.7 2003/02/12 07:23:32 mdb Exp $
package com.threerings.whirled.zone.client;
@@ -8,6 +8,7 @@ import com.threerings.presents.client.InvocationService;
import com.threerings.crowd.data.PlaceConfig;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
import com.threerings.whirled.zone.data.ZoneSummary;
@@ -17,12 +18,17 @@ import com.threerings.whirled.zone.data.ZoneSummary;
*/
public interface ZoneService extends InvocationService
{
+ /** Used to deliver responses to {@link #moveTo} requests. */
public static interface ZoneMoveListener extends InvocationListener
{
public void moveSucceeded (
int placeId, PlaceConfig config, ZoneSummary summary);
- public void moveSucceededPlusUpdate (
+ public void moveSucceededWithUpdates (
+ int placeId, PlaceConfig config, ZoneSummary summary,
+ SceneUpdate[] updates);
+
+ public void moveSucceededWithScene (
int placeId, PlaceConfig config, ZoneSummary summary,
SceneModel model);
}
@@ -33,11 +39,11 @@ public interface ZoneService extends InvocationService
*
* @param zoneId the zone id to which we want to move.
* @param sceneId the scene id to which we want to move.
- * @param sceneVers the version number of the scene object that we
- * have in our local repository.
+ * @param version the version number of the scene object that we have
+ * in our local repository.
* @param listener the object that will receive the callback when the
* request succeeds or fails.
*/
public void moveTo (Client client, int zoneId, int sceneId,
- int sceneVers, ZoneMoveListener listener);
+ int version, ZoneMoveListener listener);
}
diff --git a/src/java/com/threerings/whirled/zone/data/ZoneMarshaller.java b/src/java/com/threerings/whirled/zone/data/ZoneMarshaller.java
index 83bd03feb..6b09a41b5 100644
--- a/src/java/com/threerings/whirled/zone/data/ZoneMarshaller.java
+++ b/src/java/com/threerings/whirled/zone/data/ZoneMarshaller.java
@@ -1,5 +1,5 @@
//
-// $Id: ZoneMarshaller.java,v 1.2 2002/08/20 19:38:16 mdb Exp $
+// $Id: ZoneMarshaller.java,v 1.3 2003/02/12 07:23:32 mdb Exp $
package com.threerings.whirled.zone.data;
@@ -8,6 +8,7 @@ import com.threerings.presents.client.Client;
import com.threerings.presents.data.InvocationMarshaller;
import com.threerings.presents.dobj.InvocationResponseEvent;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
import com.threerings.whirled.zone.client.ZoneService;
import com.threerings.whirled.zone.client.ZoneService.ZoneMoveListener;
import com.threerings.whirled.zone.data.ZoneSummary;
@@ -18,10 +19,6 @@ import com.threerings.whirled.zone.data.ZoneSummary;
* on the server. Also provides an implementation of the response listener
* interfaces that marshall the response arguments and deliver them back
* to the requesting client.
- *
- *
- * $Id: ZoneMarshaller.java,v 1.2 2002/08/20 19:38:16 mdb Exp $
- *
*/
public class ZoneMarshaller extends InvocationMarshaller
implements ZoneService
@@ -42,15 +39,27 @@ public class ZoneMarshaller extends InvocationMarshaller
new Object[] { new Integer(arg1), arg2, arg3 }));
}
- /** The method id used to dispatch {@link #moveSucceededPlusUpdate}
+ /** The method id used to dispatch {@link #moveSucceededWithUpdates}
* responses. */
- public static final int MOVE_SUCCEEDED_PLUS_UPDATE = 2;
+ public static final int MOVE_SUCCEEDED_WITH_UPDATES = 2;
// documentation inherited from interface
- public void moveSucceededPlusUpdate (int arg1, PlaceConfig arg2, ZoneSummary arg3, SceneModel arg4)
+ public void moveSucceededWithUpdates (int arg1, PlaceConfig arg2, ZoneSummary arg3, SceneUpdate[] arg4)
{
omgr.postEvent(new InvocationResponseEvent(
- callerOid, requestId, MOVE_SUCCEEDED_PLUS_UPDATE,
+ callerOid, requestId, MOVE_SUCCEEDED_WITH_UPDATES,
+ new Object[] { new Integer(arg1), arg2, arg3, arg4 }));
+ }
+
+ /** The method id used to dispatch {@link #moveSucceededWithScene}
+ * responses. */
+ public static final int MOVE_SUCCEEDED_WITH_SCENE = 3;
+
+ // documentation inherited from interface
+ public void moveSucceededWithScene (int arg1, PlaceConfig arg2, ZoneSummary arg3, SceneModel arg4)
+ {
+ omgr.postEvent(new InvocationResponseEvent(
+ callerOid, requestId, MOVE_SUCCEEDED_WITH_SCENE,
new Object[] { new Integer(arg1), arg2, arg3, arg4 }));
}
@@ -63,8 +72,13 @@ public class ZoneMarshaller extends InvocationMarshaller
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (ZoneSummary)args[2]);
return;
- case MOVE_SUCCEEDED_PLUS_UPDATE:
- ((ZoneMoveListener)listener).moveSucceededPlusUpdate(
+ case MOVE_SUCCEEDED_WITH_UPDATES:
+ ((ZoneMoveListener)listener).moveSucceededWithUpdates(
+ ((Integer)args[0]).intValue(), (PlaceConfig)args[1], (ZoneSummary)args[2], (SceneUpdate[])args[3]);
+ return;
+
+ case MOVE_SUCCEEDED_WITH_SCENE:
+ ((ZoneMoveListener)listener).moveSucceededWithScene(
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (ZoneSummary)args[2], (SceneModel)args[3]);
return;
@@ -87,5 +101,5 @@ public class ZoneMarshaller extends InvocationMarshaller
});
}
- // Class file generated on 12:33:05 08/20/02.
+ // Generated on 15:03:19 02/08/03.
}
diff --git a/src/java/com/threerings/whirled/zone/server/ZoneDispatcher.java b/src/java/com/threerings/whirled/zone/server/ZoneDispatcher.java
index 863eb0f4b..50b77bbcf 100644
--- a/src/java/com/threerings/whirled/zone/server/ZoneDispatcher.java
+++ b/src/java/com/threerings/whirled/zone/server/ZoneDispatcher.java
@@ -1,5 +1,5 @@
//
-// $Id: ZoneDispatcher.java,v 1.2 2002/08/20 19:38:16 mdb Exp $
+// $Id: ZoneDispatcher.java,v 1.3 2003/02/12 07:23:32 mdb Exp $
package com.threerings.whirled.zone.server;
@@ -10,6 +10,7 @@ import com.threerings.presents.data.InvocationMarshaller;
import com.threerings.presents.server.InvocationDispatcher;
import com.threerings.presents.server.InvocationException;
import com.threerings.whirled.data.SceneModel;
+import com.threerings.whirled.data.SceneUpdate;
import com.threerings.whirled.zone.client.ZoneService;
import com.threerings.whirled.zone.client.ZoneService.ZoneMoveListener;
import com.threerings.whirled.zone.data.ZoneMarshaller;
@@ -17,10 +18,6 @@ import com.threerings.whirled.zone.data.ZoneSummary;
/**
* Dispatches requests to the {@link ZoneProvider}.
- *
- *
- * $Id: ZoneDispatcher.java,v 1.2 2002/08/20 19:38:16 mdb Exp $
- *
*/
public class ZoneDispatcher extends InvocationDispatcher
{
@@ -56,4 +53,6 @@ public class ZoneDispatcher extends InvocationDispatcher
super.dispatchRequest(source, methodId, args);
}
}
+
+ // Generated on 15:03:19 02/08/03.
}
diff --git a/src/java/com/threerings/whirled/zone/server/ZoneProvider.java b/src/java/com/threerings/whirled/zone/server/ZoneProvider.java
index ccc09c742..f8490ce1d 100644
--- a/src/java/com/threerings/whirled/zone/server/ZoneProvider.java
+++ b/src/java/com/threerings/whirled/zone/server/ZoneProvider.java
@@ -1,5 +1,5 @@
//
-// $Id: ZoneProvider.java,v 1.13 2002/12/03 06:58:57 mdb Exp $
+// $Id: ZoneProvider.java,v 1.14 2003/02/12 07:23:32 mdb Exp $
package com.threerings.whirled.zone.server;
@@ -161,10 +161,10 @@ public class ZoneProvider
}
// check to see if they need a newer version of the scene data
- SceneModel model = scmgr.getSceneModel();
+ SceneModel model = scmgr.getScene().getSceneModel();
if (sceneVersion < model.version) {
// then send the moveTo response
- listener.moveSucceededPlusUpdate(ploid, config, summary, model);
+ listener.moveSucceededWithScene(ploid, config, summary, model);
} else {
// then send the moveTo response