A whirlwind of whirled updates. Moving from scene to scene seems to mostly

work now. Scene activation is implemented. Some tests are written.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@242 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-08-14 06:51:07 +00:00
parent 5f0e2e2570
commit 89293034c8
13 changed files with 525 additions and 25 deletions
@@ -0,0 +1,215 @@
//
// $Id: SceneDirector.java,v 1.1 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.client;
import java.io.IOException;
import com.threerings.cocktail.cher.dobj.DObject;
import com.threerings.cocktail.cher.dobj.ObjectAccessException;
import com.threerings.cocktail.cher.util.IntMap;
import com.threerings.cocktail.party.client.LocationManager;
import com.threerings.cocktail.party.client.LocationObserver;
import com.threerings.cocktail.party.data.PlaceObject;
import com.threerings.whirled.Log;
import com.threerings.whirled.client.persist.SceneRepository;
import com.threerings.whirled.util.NoSuchSceneException;
import com.threerings.whirled.data.Scene;
import com.threerings.whirled.util.WhirledContext;
/**
* The scene manager is the client's interface to all things scene
* related. It interfaces with the scene repository to ensure that scene
* objects are available when the client enters a particular scene. It
* handles moving from scene to scene (it extends and replaces the
* location manager in order to do this).
*
* <p> Note that when the scene manager is in use instead of the location
* manager, scene ids instead of place oids will be supplied to {@link
* com.threerings.cocktail.party.client.LocationObserver#locationMayChange}
* and {@link
* com.threerings.cocktail.party.client.LocationObserver#locationChangeFailed}.
*/
public class SceneManager extends LocationManager
{
/**
* Creates a new scene manager with the specified context.
*/
public SceneManager (WhirledContext ctx, SceneRepository screp)
{
super(ctx);
// we'll need these for later
_ctx = ctx;
_screp = screp;
}
/**
* Returns the scene object associated with the scene we currently
* occupy or null if we currently occupy no scene.
*/
public Scene getScene ()
{
return _scene;
}
/**
* Requests that this client move the specified scene. A request will
* be made and when the response is received, the location observers
* will be notified of success or failure.
*/
public void moveTo (int sceneId)
{
// first check to see if our observers are happy with this move
// request
if (!mayMoveTo(sceneId)) {
return;
}
// complain if we're over-writing a pending request
if (_pendingSceneId != -1) {
Log.warning("We appear to have a moveTo request outstanding " +
"[psid=" + _pendingSceneId +
", nsid=" + sceneId + "].");
// but we're going to fall through and do it anyway because
// refusing to switch scenes at this point will inevitably
// result in some strange bug causing a move request to be
// dropped by the server and the client that did it to be
// totally hosed because they can no longer move to new scenes
// because they still have an outstanding request
}
// load up the pending scene so that we can communicate it's most
// recent version to the server
int sceneVers = 0;
_pendingScene = loadScene(sceneId);
// if we were unable to load it, assume a previous version of zero
if (_pendingScene != null) {
sceneVers = _pendingScene.getVersion();
}
// make a note of our pending scene id
_pendingSceneId = sceneId;
// issue a moveTo request
SceneService.moveTo(_ctx.getClient(), sceneId, sceneVers, this);
}
/**
* Called in response to a successful <code>moveTo</code> request.
*/
public void handleMoveSucceeded (int invid, int placeId)
{
// our move request was successful, deal with subscribing to our
// new place object
didMoveTo(placeId);
// since we're committed to moving to the new scene, we'll
// parallelize and go ahead and load up the new scene now rather
// than wait until subscription to our place object succeeds
// release the old scene
releaseScene(_scene);
// update our scene id tracking fields
_previousSceneId = _sceneId;
_sceneId = _pendingSceneId;
_pendingSceneId = -1;
// and load the new scene
_scene = loadScene(_sceneId);
}
/**
* Called in response to a failed <code>moveTo</code> request.
*/
public void handleMoveFailed (int invid, String reason)
{
// clear out our pending request oid
int sceneId = _pendingSceneId;
_pendingSceneId = -1;
// let our observers know that something has gone horribly awry
notifyFailure(sceneId, reason);
}
protected void recoverFailedMove (int placeId)
{
// clear out our now bogus scene tracking info
int sceneId = _sceneId;
_sceneId = -1;
releaseScene(_scene);
_scene = null;
// 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);
}
}
/**
* Loads a scene from the repository. If the scene is cached, it will
* be returned from the cache instead.
*/
protected Scene loadScene (int sceneId)
{
// first look in the cache
Scene scene = (Scene)_scache.get(sceneId);
// load from the repository if it's not cached
if (scene == null) {
try {
scene = _screp.loadScene(sceneId);
_scache.put(sceneId, scene);
} catch (NoSuchSceneException nsse) {
// nothing special here, just fall through and return null
} catch (IOException ioe) {
// complain first, then return null
Log.warning("Error loading scene [scid=" + sceneId +
", error=" + ioe + "].");
}
}
return scene;
}
/**
* Unloads a scene that was previously loaded via {@link #loadScene}.
* The scene will probably continue to live in the cache for a while
* in case we quickly return to it.
*/
protected void releaseScene (Scene scene)
{
// we're cool if we're called with null
if (scene == null) {
return;
}
}
protected WhirledContext _ctx;
protected SceneRepository _screp;
protected IntMap _scache = new IntMap();
/** The scene object of the scene we currently occupy. */
protected Scene _scene;
/** The id of the scene we currently occupy. */
protected int _sceneId = -1;
/** Our most recent copy of the scene we're about to enter. */
protected Scene _pendingScene;
/**
* The id of the scene for which we have an outstanding moveTo
* request, or -1 if we have no outstanding request.
*/
protected int _pendingSceneId = -1;
/** The id of the scene we previously occupied. */
protected int _previousSceneId = -1;
}
@@ -1,5 +1,5 @@
//
// $Id: SceneService.java,v 1.1 2001/08/11 04:09:50 mdb Exp $
// $Id: SceneService.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.client;
@@ -10,10 +10,29 @@ import com.threerings.whirled.Log;
/**
* The scene service class provides the client interface to the scene
* related invocation services.
* related invocation services (e.g. moving from scene to scene).
*/
public class SceneService
{
/** The module name for the scene services. */
public static final String MODULE = "whirled!scene";
/**
* Requests that that this client's body be moved to the specified
* 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.
*/
public static void moveTo (Client client, int sceneId,
int sceneVers, SceneManager rsptarget)
{
InvocationManager invmgr = client.getInvocationManager();
Object[] args = new Object[] {
new Integer(sceneId), new Integer(sceneVers) };
invmgr.invoke(MODULE, "MoveTo", args, rsptarget);
Log.info("Sent moveTo request [scene=" + sceneId +
", version=" + sceneVers + "].");
}
}
@@ -1,5 +1,5 @@
//
// $Id: SceneRepository.java,v 1.1 2001/08/11 04:09:50 mdb Exp $
// $Id: SceneRepository.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.client.persist;
@@ -15,7 +15,7 @@ import com.threerings.whirled.util.NoSuchSceneException;
* bundles that are periodically distributed to bring all clients into
* sync with the latest snapshot of the scene database.
*
* @see com.threerings.whirled.client.Scene
* @see com.threerings.whirled.data.Scene
*/
public interface SceneRepository
{
@@ -27,6 +27,16 @@ public interface SceneRepository
* @exception NoSuchSceneException thrown if no scene exists with the
* specified scene id.
*/
public Scene getScene (int sceneid)
public Scene loadScene (int sceneId)
throws IOException, NoSuchSceneException;
/**
* Updates the specified scene in the repository with the information
* provided in the scene object.
*
* @exception IOException thrown if an error occurs attempting to
* update the scene.
*/
public void updateScene (Scene scene)
throws IOException;
}
@@ -0,0 +1,31 @@
//
// $Id: DummyScene.java,v 1.1 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.client.test;
import com.threerings.whirled.data.Scene;
public class DummyScene implements Scene
{
public DummyScene (int sceneId)
{
_sceneId = sceneId;
}
public int getId ()
{
return _sceneId;
}
public int getVersion ()
{
return 1;
}
public int[] getExitIds ()
{
return null;
}
protected int _sceneId;
}
@@ -1,5 +1,5 @@
//
// $Id: SceneRegistry.java,v 1.1 2001/08/11 04:09:50 mdb Exp $
// $Id: SceneRegistry.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.server;
@@ -44,6 +44,7 @@ public class SceneRegistry
// we'll use this to do database stuff
_invoker = new Invoker();
_invoker.start();
}
/**
@@ -91,6 +92,8 @@ public class SceneRegistry
return;
}
Log.info("Resolving scene [id=" + sceneId + "].");
// otherwise we've got to resolve the scene and call them back
// later; we can manipulate the penders table with impunity here
// because we only do so on the dobjmgr thread
@@ -113,6 +116,8 @@ public class SceneRegistry
// keywords...
final int fsceneId = sceneId;
Log.info("Invoking scene repository [id=" + sceneId + "].");
// then we queue up an execution unit that'll load the scene
// and initialize it and all that
_invoker.postUnit(new Invoker.Unit() {
@@ -120,7 +125,7 @@ public class SceneRegistry
public boolean invoke ()
{
try {
_scene = _screp.getScene(fsceneId);
_scene = _screp.loadScene(fsceneId);
} catch (Exception e) {
_cause = e;
}
@@ -1,5 +1,5 @@
//
// $Id: WhirledServer.java,v 1.1 2001/08/11 04:09:50 mdb Exp $
// $Id: WhirledServer.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.server;
@@ -9,7 +9,7 @@ import com.threerings.cocktail.party.server.PartyServer;
import com.threerings.whirled.Log;
import com.threerings.whirled.server.persist.SceneRepository;
import com.threerings.whirled.server.persist.DummySceneRepository;
import com.threerings.whirled.server.test.DummySceneRepository;
/**
* The whirled server extends the party server and provides access to
@@ -75,7 +75,7 @@ public class WhirledServer extends PartyServer
protected final static String PROVIDERS_KEY = CONFIG_KEY + ".providers";
// scene repository related configuration info
protected final static String SCENEREP_KEY = "scene_rep";
protected final static String SCENEREP_KEY = CONFIG_KEY + ".scene_rep";
protected final static String DEF_SCENEREP =
DummySceneRepository.class.getName();
}
@@ -1,10 +1,13 @@
//
// $Id: DummySceneRepository.java,v 1.1 2001/08/11 04:09:50 mdb Exp $
// $Id: DummySceneRepository.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.server.persist;
package com.threerings.whirled.server.test;
import java.io.IOException;
import com.threerings.whirled.Log;
import com.threerings.whirled.data.Scene;
import com.threerings.whirled.server.persist.SceneRepository;
import com.threerings.whirled.util.NoSuchSceneException;
/**
@@ -15,10 +18,11 @@ import com.threerings.whirled.util.NoSuchSceneException;
public class DummySceneRepository implements SceneRepository
{
// documentation inherited
public Scene getScene (int sceneid)
public Scene loadScene (int sceneId)
throws IOException, NoSuchSceneException
{
return null;
Log.info("Creating dummy scene [id=" + sceneId + "].");
return new DummyScene(sceneId);
}
// documentation inherited
@@ -1,5 +1,5 @@
//
// $Id: SceneRepository.java,v 1.1 2001/08/11 04:09:50 mdb Exp $
// $Id: SceneRepository.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.server.persist;
@@ -17,7 +17,7 @@ public interface SceneRepository
* @exception NoSuchSceneException thrown if no scene exists with the
* specified scene id.
*/
public Scene getScene (int sceneid)
public Scene loadScene (int sceneId)
throws IOException, NoSuchSceneException;
/**
@@ -0,0 +1,19 @@
//
// $Id: WhirledContext.java,v 1.1 2001/08/14 06:51:07 mdb Exp $
package com.threerings.whirled.util;
import com.threerings.cocktail.party.util.PartyContext;
import com.threerings.whirled.client.SceneManager;
/**
* The whirled context provides access to the various managers, etc. that
* are needed by the whirled client code.
*/
public interface WhirledContext extends PartyContext
{
/**
* Returns a reference to the scene manager.
*/
public SceneManager getSceneManager ();
}