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:
@@ -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 ();
|
||||
}
|
||||
Reference in New Issue
Block a user