From 97197d49ccc913a3cb187ed9701aee4718d6ff47 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Sun, 26 May 2002 02:24:46 +0000 Subject: [PATCH] Added support for initiating a place/scene/zone transition from the server; chat director no longer needs to wait until we're logged on to register itself with the invocation director. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1393 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../crowd/chat/client/ChatDirector.java | 14 +- .../crowd/client/LocationDirector.java | 37 ++++- .../threerings/crowd/data/LocationCodes.java | 5 +- .../crowd/server/LocationProvider.java | 157 ++++++++++++------ .../whirled/client/SceneDirector.java | 32 +++- .../whirled/server/SceneProvider.java | 25 ++- .../whirled/server/SceneRegistry.java | 4 +- .../whirled/zone/client/ZoneDirector.java | 20 ++- .../whirled/zone/server/ZoneProvider.java | 26 ++- .../whirled/zone/server/ZoneRegistry.java | 4 +- 10 files changed, 251 insertions(+), 73 deletions(-) diff --git a/src/java/com/threerings/crowd/chat/client/ChatDirector.java b/src/java/com/threerings/crowd/chat/client/ChatDirector.java index 7d8d3cc13..18d9d6822 100644 --- a/src/java/com/threerings/crowd/chat/client/ChatDirector.java +++ b/src/java/com/threerings/crowd/chat/client/ChatDirector.java @@ -1,5 +1,5 @@ // -// $Id: ChatDirector.java,v 1.21 2002/05/22 21:44:54 shaper Exp $ +// $Id: ChatDirector.java,v 1.22 2002/05/26 02:24:45 mdb Exp $ package com.threerings.crowd.chat; @@ -34,15 +34,9 @@ public class ChatDirector // keep the context around _ctx = ctx; - // register a client observer that will register us as the chat - // receiver when we log on - _ctx.getClient().addClientObserver(new ClientAdapter() { - public void clientDidLogon (Client client) - { - client.getInvocationDirector().registerReceiver( - MODULE_NAME, ChatDirector.this); - } - }); + // register for chat notifications + _ctx.getClient().getInvocationDirector().registerReceiver( + MODULE_NAME, this); // register ourselves as a location observer _ctx.getLocationDirector().addLocationObserver(this); diff --git a/src/java/com/threerings/crowd/client/LocationDirector.java b/src/java/com/threerings/crowd/client/LocationDirector.java index 5e3bf0ad2..1ca19a6f2 100644 --- a/src/java/com/threerings/crowd/client/LocationDirector.java +++ b/src/java/com/threerings/crowd/client/LocationDirector.java @@ -1,5 +1,5 @@ // -// $Id: LocationDirector.java,v 1.19 2002/05/22 21:46:53 shaper Exp $ +// $Id: LocationDirector.java,v 1.20 2002/05/26 02:24:46 mdb Exp $ package com.threerings.crowd.client; @@ -10,6 +10,7 @@ import com.samskivert.util.ObserverList; import com.samskivert.util.ObserverList.ObserverOp; import com.threerings.presents.client.Client; +import com.threerings.presents.client.InvocationReceiver; import com.threerings.presents.client.SessionObserver; import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.DObjectManager; @@ -18,6 +19,7 @@ import com.threerings.presents.dobj.Subscriber; import com.threerings.crowd.Log; import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.LocationCodes; import com.threerings.crowd.data.PlaceConfig; import com.threerings.crowd.data.PlaceObject; import com.threerings.crowd.util.CrowdContext; @@ -30,7 +32,7 @@ import com.threerings.crowd.util.CrowdContext; * before actually issuing the request. */ public class LocationDirector - implements SessionObserver, Subscriber + implements LocationCodes, SessionObserver, Subscriber, InvocationReceiver { /** * Used to recover from a moveTo request that was accepted but @@ -57,6 +59,10 @@ public class LocationDirector // register ourselves as a client observer ctx.getClient().addClientObserver(this); + + // register for location notifications + _ctx.getClient().getInvocationDirector().registerReceiver( + MODULE_NAME, this); } /** @@ -174,11 +180,13 @@ public class LocationDirector */ public void didMoveTo (int placeId, PlaceConfig config) { + // keep track of our previous place id + _previousPlaceId = _placeId; + // do some cleaning up in case we were previously in a place didLeavePlace(); // make a note that we're now mostly in the new location - _previousPlaceId = _placeId; _placeId = placeId; Class cclass = config.getControllerClass(); @@ -199,12 +207,12 @@ public class LocationDirector } /** - * Called when we're leaving our current location. Informs the + * Called when we're leaving our current location. Informs the * location's controller that we're departing, unsubscribes from the * location's place object, and clears out our internal place * information. */ - protected void didLeavePlace () + public void didLeavePlace () { if (_plobj != null) { // let the old controller know that things are going away @@ -244,6 +252,7 @@ public class LocationDirector notifyFailure(placeId, reason); } + // documentation inherited from interface public void clientDidLogon (Client client) { // get a copy of our body object @@ -270,6 +279,7 @@ public class LocationDirector // we'll want to be going there straight away } + // documentation inherited from interface public void clientDidLogoff (Client client) { // clear ourselves out and inform observers of our departure @@ -307,6 +317,23 @@ public class LocationDirector notifyFailure(placeId, reason); } + /** + * Called when the server has decided to forcibly move us to another + * room. The server first ejects us from our previous room and then + * sends us a notification with our new location. We then turn around + * and issue a standard moveTo request. + */ + public void handleMoveNotification (int placeId) + { + Log.info("Moving at request of server [placeId=" + placeId + "]."); + + // clear out our old place information + didLeavePlace(); + + // move to the new place + moveTo(placeId); + } + /** * Called when we receive the place object to which we subscribed * after a successful moveTo request. diff --git a/src/java/com/threerings/crowd/data/LocationCodes.java b/src/java/com/threerings/crowd/data/LocationCodes.java index 345826761..1d0c8d7c9 100644 --- a/src/java/com/threerings/crowd/data/LocationCodes.java +++ b/src/java/com/threerings/crowd/data/LocationCodes.java @@ -1,5 +1,5 @@ // -// $Id: LocationCodes.java,v 1.2 2002/04/15 18:06:19 mdb Exp $ +// $Id: LocationCodes.java,v 1.3 2002/05/26 02:24:46 mdb Exp $ package com.threerings.crowd.data; @@ -27,6 +27,9 @@ public interface LocationCodes extends InvocationCodes * LocationDirector#handleMoveFailed}. */ public static final String MOVE_FAILED_RESPONSE = "MoveFailed"; + /** The message identifier for a move notification. */ + public static final String MOVE_NOTIFICATION = "Move"; + /** An error code indicating that a place identified by a particular * place id does not exist. Usually generated by a failed moveTo * request. */ diff --git a/src/java/com/threerings/crowd/server/LocationProvider.java b/src/java/com/threerings/crowd/server/LocationProvider.java index f6d313c5c..361783968 100644 --- a/src/java/com/threerings/crowd/server/LocationProvider.java +++ b/src/java/com/threerings/crowd/server/LocationProvider.java @@ -1,5 +1,5 @@ // -// $Id: LocationProvider.java,v 1.13 2002/05/02 21:19:28 mdb Exp $ +// $Id: LocationProvider.java,v 1.14 2002/05/26 02:24:46 mdb Exp $ package com.threerings.crowd.server; @@ -20,8 +20,8 @@ import com.threerings.crowd.data.PlaceObject; /** * This class provides the server end of the location services. */ -public class LocationProvider - extends InvocationProvider implements LocationCodes +public class LocationProvider extends InvocationProvider + implements LocationCodes { /** * Constructs a location provider and registers it with the invocation @@ -32,6 +32,7 @@ public class LocationProvider InvocationManager invmgr, RootDObjectManager omgr, PlaceRegistry plreg) { // we'll need these later + _invmgr = invmgr; _omgr = omgr; _plreg = plreg; @@ -42,8 +43,8 @@ public class LocationProvider /** * Processes a request from a client to move to a new place. */ - public void handleMoveToRequest (BodyObject source, int invid, - int placeId) + public void handleMoveToRequest ( + BodyObject source, int invid, int placeId) { try { // do the move @@ -90,62 +91,124 @@ public class LocationProvider return pmgr.getConfig(); } - // acquire a lock on the body object to ensure that rapid fire - // moveto requests don't break things - if (!source.acquireLock("moveToLock")) { - // if we're still locked, a previous moveTo request hasn't - // been fully processed - throw new ServiceFailedException(MOVE_IN_PROGRESS); + try { + // acquire a lock on the body object to ensure that rapid fire + // moveTo requests don't break things + if (!source.acquireLock("moveToLock")) { + // if we're still locked, a previous moveTo request hasn't + // been fully processed + throw new ServiceFailedException(MOVE_IN_PROGRESS); + } + + PlaceObject place = pmgr.getPlaceObject(); + try { + source.startTransaction(); + + // remove them from any previous location + leaveOccupiedPlace(source); + + // set the body's new location + source.setLocation(place.getOid()); + + } finally { + source.commitTransaction(); + } + + try { + place.startTransaction(); + + // generate a new occupant info record and add it to the + // target location + OccupantInfo info = pmgr.buildOccupantInfo(source); + if (info != null) { + place.addToOccupantInfo(info); + } + + // add the body oid to the place object's occupant list + place.addToOccupants(bodoid); + + } finally { + place.commitTransaction(); + } + + } finally { + // and finally queue up a lock release event to release the + // lock once all these events are processed + source.releaseLock("moveToLock"); } - // find out if they were previously in some other location - if (source.location != -1) { - // remove them from the occupant list of the previous location - try { - PlaceObject pold = (PlaceObject) - _omgr.getObject(source.location); - if (pold != null) { - Object key = new Integer(bodoid); + return pmgr.getConfig(); + } + + /** + * Removes the specified body from the place object they currently + * occupy. Does nothing if the body is not currently in a place. + */ + public static void leaveOccupiedPlace (BodyObject source) + { + int oldloc = source.location; + int bodoid = source.getOid(); + + // nothing to do if they weren't previously in some location + if (oldloc == -1) { + return; + } + + // remove them from the occupant list + try { + PlaceObject pold = (PlaceObject)_omgr.getObject(oldloc); + if (pold != null) { + Object key = new Integer(bodoid); + try { + pold.startTransaction(); // remove their occupant info (which is keyed on oid) pold.removeFromOccupantInfo(key); // and remove them from the occupant list pold.removeFromOccupants(bodoid); - } else { - Log.info("Body's prior location no longer around? " + - "[boid=" + bodoid + - ", poid=" + source.location + "]."); + } finally { + pold.commitTransaction(); } - } catch (ClassCastException cce) { - Log.warning("Body claims to be at location which " + - "references non-PlaceObject!? " + - "[boid=" + bodoid + - ", poid=" + source.location + "]."); + } else { + Log.info("Body's prior location no longer around? " + + "[boid=" + bodoid + ", poid=" + oldloc + "]."); } + + } catch (ClassCastException cce) { + Log.warning("Body claims to occupy non-PlaceObject!? " + + "[boid=" + bodoid + ", poid=" + oldloc + + ", error=" + cce + "]."); } - // set the body's new location - PlaceObject place = pmgr.getPlaceObject(); - source.setLocation(place.getOid()); - - // generate a new occupant info record and add it to the target - // location - OccupantInfo info = pmgr.buildOccupantInfo(source); - if (info != null) { - place.addToOccupantInfo(info); - } - - // add the body object id to the place object's occupant list - place.addToOccupants(bodoid); - - // and finally queue up a lock release event to release the lock - // once all these events are processed - source.releaseLock("moveToLock"); - - return pmgr.getConfig(); + // clear out their location oid + source.setLocation(-1); } + /** + * Forcibly moves the specified body object to the new place. This is + * accomplished by first removing the client from their old location + * and then sending the client a notification, instructing it to move + * to the new location (which it does using the normal moveTo + * service). This has the benefit that the client is removed from + * their old place regardless of whether or not they are cooperating. + * If they choose to ignore the forced move request, they will remain + * in limbo, unable to do much of anything. + */ + public void moveBody (BodyObject source, int placeId) + { + // first remove them from their old place + leaveOccupiedPlace(source); + + // then send a move notification + _invmgr.sendNotification( + source.getOid(), MODULE_NAME, MOVE_NOTIFICATION, + new Object[] { new Integer(placeId) }); + } + + /** The invocation manager with which we interoperate. */ + protected static InvocationManager _invmgr; + /** The distributed object manager with which we interoperate. */ protected static RootDObjectManager _omgr; diff --git a/src/java/com/threerings/whirled/client/SceneDirector.java b/src/java/com/threerings/whirled/client/SceneDirector.java index 5f6670a3a..e06441e51 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.13 2002/05/22 21:48:44 shaper Exp $ +// $Id: SceneDirector.java,v 1.14 2002/05/26 02:24:46 mdb Exp $ package com.threerings.whirled.client; @@ -234,6 +234,36 @@ public class SceneDirector _locdir.failedToMoveTo(sceneId, reason); } + /** + * Called to clean up our place and scene state information when we + * leave a scene. + */ + public void didLeaveScene () + { + // let the location director know what's up + _locdir.didLeavePlace(); + + // clear out our own scene state + clearScene(); + } + + /** + * Called when the server has decided to forcibly move us to another + * scene. The server first ejects us from our previous scene and then + * sends us a notification with our new location. We then turn around + * and issue a standard moveTo request. + */ + public void handleMoveNotification (int sceneId) + { + Log.info("Moving at request of server [sceneId=" + sceneId + "]."); + + // clear out our old scene and place data + didLeaveScene(); + + // move to the new scene + moveTo(sceneId); + } + /** * Called when something breaks down in the process of performing a * moveTo request. diff --git a/src/java/com/threerings/whirled/server/SceneProvider.java b/src/java/com/threerings/whirled/server/SceneProvider.java index 16b002e11..7f17c4315 100644 --- a/src/java/com/threerings/whirled/server/SceneProvider.java +++ b/src/java/com/threerings/whirled/server/SceneProvider.java @@ -1,8 +1,9 @@ // -// $Id: SceneProvider.java,v 1.8 2002/04/15 16:28:03 shaper Exp $ +// $Id: SceneProvider.java,v 1.9 2002/05/26 02:24:46 mdb Exp $ package com.threerings.whirled.server; +import com.threerings.presents.server.InvocationManager; import com.threerings.presents.server.InvocationProvider; import com.threerings.presents.server.ServiceFailedException; @@ -26,8 +27,9 @@ public class SceneProvider extends InvocationProvider * Constructs a scene provider that will interact with the supplied * scene registry. */ - public SceneProvider (SceneRegistry screg) + public SceneProvider (InvocationManager invmgr, SceneRegistry screg) { + _invmgr = invmgr; _screg = screg; } @@ -101,6 +103,25 @@ public class SceneProvider extends InvocationProvider } } + /** + * Ejects the specified body from their current scene and sends them a + * request to move to the specified new scene. This is the + * scene-equivalent to {@link LocationProvider#moveBody}. + */ + public void moveBody (BodyObject source, int sceneId) + { + // first remove them from their old place + LocationProvider.leaveOccupiedPlace(source); + + // then send a move notification + _invmgr.sendNotification( + source.getOid(), MODULE_NAME, MOVE_NOTIFICATION, + new Object[] { new Integer(sceneId) }); + } + + /** The invocation manager with which we interact. */ + protected InvocationManager _invmgr; + /** The scene registry with which we interact. */ protected SceneRegistry _screg; } diff --git a/src/java/com/threerings/whirled/server/SceneRegistry.java b/src/java/com/threerings/whirled/server/SceneRegistry.java index e01083225..340bd37b9 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.14 2002/05/24 05:58:55 mdb Exp $ +// $Id: SceneRegistry.java,v 1.15 2002/05/26 02:24:46 mdb Exp $ package com.threerings.whirled.server; @@ -50,7 +50,7 @@ public class SceneRegistry _scfact = new DefaultRuntimeSceneFactory(); // create/register a scene provider with the invocation services - SceneProvider provider = new SceneProvider(this); + SceneProvider provider = new SceneProvider(invmgr, this); invmgr.registerProvider(SceneProvider.MODULE_NAME, provider); } diff --git a/src/java/com/threerings/whirled/zone/client/ZoneDirector.java b/src/java/com/threerings/whirled/zone/client/ZoneDirector.java index 677ece4dd..81dcbb425 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.4 2001/12/17 04:11:40 mdb Exp $ +// $Id: ZoneDirector.java,v 1.5 2002/05/26 02:24:46 mdb Exp $ package com.threerings.whirled.zone.client; @@ -149,6 +149,24 @@ public class ZoneDirector notifyObservers(reason); } + /** + * Called when the server has decided to forcibly move us to another + * zone and scene. The server first ejects us from our previous scene + * and then sends us a notification with our new location. We then + * turn around and issue a standard moveTo request. + */ + public void handleMoveNotification (int zoneId, int sceneId) + { + Log.info("Moving at request of server [zoneId=" + zoneId + + ", sceneId=" + sceneId + "]."); + + // clear out our old scene and place data + _scdir.didLeaveScene(); + + // move to the new zone and scene + moveTo(zoneId, sceneId); + } + /** * Notifies observers of success or failure, depending on the type of * object provided as data. diff --git a/src/java/com/threerings/whirled/zone/server/ZoneProvider.java b/src/java/com/threerings/whirled/zone/server/ZoneProvider.java index b0e06acdf..447fcf5dd 100644 --- a/src/java/com/threerings/whirled/zone/server/ZoneProvider.java +++ b/src/java/com/threerings/whirled/zone/server/ZoneProvider.java @@ -1,8 +1,9 @@ // -// $Id: ZoneProvider.java,v 1.7 2002/05/03 00:00:17 mdb Exp $ +// $Id: ZoneProvider.java,v 1.8 2002/05/26 02:24:46 mdb Exp $ package com.threerings.whirled.zone.server; +import com.threerings.presents.server.InvocationManager; import com.threerings.presents.server.InvocationProvider; import com.threerings.presents.server.ServiceFailedException; @@ -33,8 +34,10 @@ public class ZoneProvider * constructed and registered by the {@link ZoneRegistry}, which a * zone-using system must create and initialize in their server. */ - public ZoneProvider (ZoneRegistry zonereg, SceneRegistry screg) + public ZoneProvider ( + InvocationManager invmgr, ZoneRegistry zonereg, SceneRegistry screg) { + _invmgr = invmgr; _zonereg = zonereg; _screg = screg; } @@ -174,6 +177,25 @@ public class ZoneProvider } } + /** + * Ejects the specified body from their current scene and sends them a + * request to move to the specified new zone and scene. This is the + * zone-equivalent to {@link LocationProvider#moveBody}. + */ + public void moveBody (BodyObject source, int zoneId, int sceneId) + { + // first remove them from their old place + LocationProvider.leaveOccupiedPlace(source); + + // then send a move notification + _invmgr.sendNotification( + source.getOid(), MODULE_NAME, MOVE_NOTIFICATION, + new Object[] { new Integer(zoneId), new Integer(sceneId) }); + } + + /** The invocation manager with which we interact. */ + protected InvocationManager _invmgr; + /** The zone registry with which we communicate. */ protected ZoneRegistry _zonereg; diff --git a/src/java/com/threerings/whirled/zone/server/ZoneRegistry.java b/src/java/com/threerings/whirled/zone/server/ZoneRegistry.java index 41362a051..9e24f4b05 100644 --- a/src/java/com/threerings/whirled/zone/server/ZoneRegistry.java +++ b/src/java/com/threerings/whirled/zone/server/ZoneRegistry.java @@ -1,5 +1,5 @@ // -// $Id: ZoneRegistry.java,v 1.6 2002/03/28 23:59:33 mdb Exp $ +// $Id: ZoneRegistry.java,v 1.7 2002/05/26 02:24:46 mdb Exp $ package com.threerings.whirled.zone.server; @@ -24,7 +24,7 @@ public class ZoneRegistry { // create a zone provider and register it with the invocation // services - ZoneProvider provider = new ZoneProvider(this, screg); + ZoneProvider provider = new ZoneProvider(invmgr, this, screg); invmgr.registerProvider(ZoneProvider.MODULE_NAME, provider); }