diff --git a/src/java/com/threerings/stage/client/StageScenePanel.java b/src/java/com/threerings/stage/client/StageScenePanel.java
index f0f8aae00..f3347f675 100644
--- a/src/java/com/threerings/stage/client/StageScenePanel.java
+++ b/src/java/com/threerings/stage/client/StageScenePanel.java
@@ -551,6 +551,9 @@ public class StageScenePanel extends MisoScenePanel
*/
protected boolean isPortal (Location loc)
{
+ if (_scene == null) {
+ return false;
+ }
Iterator iter = _scene.getPortals();
while (iter.hasNext()) {
Portal p = (Portal)iter.next();
diff --git a/src/java/com/threerings/whirled/client/SceneDirector.java b/src/java/com/threerings/whirled/client/SceneDirector.java
index e9bbcf1bd..95a2605c3 100644
--- a/src/java/com/threerings/whirled/client/SceneDirector.java
+++ b/src/java/com/threerings/whirled/client/SceneDirector.java
@@ -60,6 +60,18 @@ public class SceneDirector extends BasicDirector
implements SceneCodes, LocationDirector.FailureHandler,
SceneReceiver, SceneService.SceneMoveListener
{
+ /**
+ * Used to recover from a problem after a completed moveTo.
+ */
+ public static interface MoveHandler
+ {
+ /**
+ * Should instruct the client to move the last known working
+ * location (as well as clean up after the failed moveTo request).
+ */
+ public void recoverMoveTo (int sceneId);
+ }
+
/**
* Creates a new scene director with the specified context.
*
@@ -371,6 +383,23 @@ public class SceneDirector extends BasicDirector
moveTo(sceneId);
}
+ /**
+ * Sets the moveHandler for use in recoverFailedMove.
+ */
+ public void setMoveHandler (MoveHandler handler)
+ {
+ if (_moveHandler != null) {
+ Log.warning("Requested to set move handler, but we've " +
+ "already got one. The conflicting entities will " +
+ "likely need to perform more sophisticated " +
+ "coordination to deal with failures. " +
+ "[old=" + _moveHandler + ", new=" + handler + "].");
+
+ } else {
+ _moveHandler = handler;
+ }
+ }
+
/**
* Called when something breaks down in the process of performing a
* moveTo request.
@@ -386,7 +415,15 @@ public class SceneDirector extends BasicDirector
// if we were previously somewhere (and that somewhere isn't where
// we just tried to go), try going back to that happy place
if (_previousSceneId != -1 && _previousSceneId != sceneId) {
- moveTo(_previousSceneId);
+ // if we have a move handler use that
+ if (_moveHandler != null) {
+ _moveHandler.recoverMoveTo(_previousSceneId);
+
+ } else {
+ Log.info("Recovering failed scene move [_previousSceneId=" +
+ _previousSceneId + "].");
+ moveTo(_previousSceneId);
+ }
}
}
@@ -507,4 +544,7 @@ public class SceneDirector extends BasicDirector
/** The id of the scene we previously occupied. */
protected int _previousSceneId = -1;
+
+ /** Reference to our move handler. */
+ protected MoveHandler _moveHandler = null;
}
diff --git a/src/java/com/threerings/whirled/zone/client/ZoneDirector.java b/src/java/com/threerings/whirled/zone/client/ZoneDirector.java
index 9fd6b4923..4b8ed2bb0 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.16 2004/08/27 02:20:50 mdb Exp $
+// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
@@ -49,7 +49,8 @@ import com.threerings.whirled.zone.util.ZoneUtil;
* generate an overview map or similar.
*/
public class ZoneDirector extends BasicDirector
- implements ZoneReceiver, ZoneService.ZoneMoveListener
+ implements ZoneReceiver, ZoneService.ZoneMoveListener,
+ SceneDirector.MoveHandler
{
/**
* Constructs a zone director with the supplied context, and delegate
@@ -62,6 +63,7 @@ public class ZoneDirector extends BasicDirector
super(ctx);
_ctx = ctx;
_scdir = scdir;
+ _scdir.setMoveHandler(this);
// register for zone notifications
_ctx.getClient().getInvocationDirector().registerReceiver(
@@ -165,6 +167,7 @@ public class ZoneDirector extends BasicDirector
// clear out our business
_zservice = null;
_summary = null;
+ _previousZoneId = -1;
}
/**
@@ -174,6 +177,11 @@ public class ZoneDirector extends BasicDirector
public void moveSucceeded (
int placeId, PlaceConfig config, ZoneSummary summary)
{
+ if (_summary != null) {
+ // keep track of our previous zone info
+ _previousZoneId = _summary.zoneId;
+ }
+
// keep track of the summary
_summary = summary;
@@ -246,6 +254,20 @@ public class ZoneDirector extends BasicDirector
moveTo(zoneId, sceneId, null);
}
+ /**
+ * Called when something breaks down after successfully completely a
+ * moveTo request.
+ */
+ public void recoverMoveTo (int sceneId)
+ {
+ if (_previousZoneId != -1) {
+ moveTo(_previousZoneId, sceneId);
+
+ } else {
+ _scdir.moveTo(sceneId);
+ }
+ }
+
/**
* Notifies observers of success or failure, depending on the type of
* object provided as data.
@@ -287,4 +309,7 @@ public class ZoneDirector extends BasicDirector
/** Our zone observer list. */
protected ArrayList _observers = new ArrayList();
+
+ /** Our previous zone id. */
+ protected int _previousZoneId = -1;
}