diff --git a/src/java/com/threerings/whirled/spot/server/SpotProvider.java b/src/java/com/threerings/whirled/spot/server/SpotProvider.java index 4fcf6b54d..a697f1a7f 100644 --- a/src/java/com/threerings/whirled/spot/server/SpotProvider.java +++ b/src/java/com/threerings/whirled/spot/server/SpotProvider.java @@ -1,5 +1,5 @@ // -// $Id: SpotProvider.java,v 1.2 2001/12/14 23:12:39 mdb Exp $ +// $Id: SpotProvider.java,v 1.3 2001/12/16 05:15:27 mdb Exp $ package com.threerings.whirled.spot.server; @@ -95,8 +95,9 @@ public class SpotProvider extends InvocationProvider SceneRegistry.ResolutionListener rl = new SceneRegistry.ResolutionListener() { public void sceneWasResolved (SceneManager scmgr) { + SpotSceneManager sscmgr = (SpotSceneManager)scmgr; finishTraversePortalRequest( - fsource, finvid, scmgr, fsceneVer, + fsource, finvid, sscmgr, fsceneVer, fportalId, destLocId); } @@ -125,12 +126,13 @@ public class SpotProvider extends InvocationProvider * to have been loaded into the server. */ protected void finishTraversePortalRequest ( - BodyObject source, int invid, SceneManager scmgr, + BodyObject source, int invid, SpotSceneManager scmgr, int sceneVer, int exitPortalId, int destLocId) { // move to the place object associated with this scene PlaceObject plobj = scmgr.getPlaceObject(); int ploid = plobj.getOid(); + int bodyOid = source.getOid(); // if they were in a scene (and at a location) prior to issuing // this traverse portal request, we need to send a notification to @@ -144,17 +146,15 @@ public class SpotProvider extends InvocationProvider // ripping apart moveTo and restructuring the code with this // requirement in mind int oldLocId = - updateLocation(source.location, source.getOid(), exitPortalId); + updateLocation(source.location, bodyOid, exitPortalId); + + // let the destination scene manager know that we're coming in + scmgr.mapEnteringBody(bodyOid, destLocId); try { // try doing the actual move PlaceConfig config = LocationProvider.moveTo(source, ploid); - // now that the move succeeded, we need to update the occupant - // info in the new place object with this user's entry - // location - updateLocation(ploid, source.getOid(), destLocId); - // check to see if they need a newer version of the scene data SceneModel model = scmgr.getSceneModel(); if (sceneVer < model.version) { @@ -173,7 +173,11 @@ public class SpotProvider extends InvocationProvider // we need to undo the move to the exit portal location that // we enacted earlier - updateLocation(source.location, source.getOid(), oldLocId); + updateLocation(source.location, bodyOid, oldLocId); + + // and let the destination scene manager know that we're no + // longer coming in + scmgr.clearEnteringBody(bodyOid); } } diff --git a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java index 3b67f88f0..f886544b3 100644 --- a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java +++ b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java @@ -1,8 +1,10 @@ // -// $Id: SpotSceneManager.java,v 1.1 2001/12/14 00:12:32 mdb Exp $ +// $Id: SpotSceneManager.java,v 1.2 2001/12/16 05:15:27 mdb Exp $ package com.threerings.whirled.spot.server; +import com.samskivert.util.IntIntMap; + import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.Subscriber; import com.threerings.presents.dobj.ObjectAccessException; @@ -10,6 +12,7 @@ import com.threerings.presents.server.ServiceFailedException; import com.threerings.crowd.chat.ChatProvider; import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.OccupantInfo; import com.threerings.whirled.server.SceneManager; import com.threerings.whirled.spot.Log; @@ -24,6 +27,26 @@ import com.threerings.whirled.spot.data.SpotOccupantInfo; public class SpotSceneManager extends SceneManager implements SpotCodes { + /** + * 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. + */ + public void mapEnteringBody (int bodyOid, int locationId) + { + _entering.put(bodyOid, locationId); + } + + /** + * If scene entry fails, this can be called to undo a scene entry + * mapping. + */ + public void clearEnteringBody (int bodyOid) + { + _entering.remove(bodyOid); + } + // documentation inherited protected void gotSceneData () { @@ -62,6 +85,27 @@ public class SpotSceneManager extends SceneManager _locationOccs = new int[_sscene.getLocationCount()]; } + /** + * 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. + */ + 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(); + } + ((SpotOccupantInfo)info).locationId = entryLocId; + } + /** * Called by the {@link SpotProvider} when we receive a request by a * user to occupy a particular location. @@ -169,4 +213,8 @@ public class SpotSceneManager extends SceneManager /** Oids of the bodies that occupy each of our locations. */ protected int[] _locationOccs; + + /** A table of mappings from body oids to entry location ids for + * bodies that are entering our scene. */ + protected IntIntMap _entering = new IntIntMap(); }