diff --git a/src/java/com/threerings/whirled/server/AbstractSceneMoveHandler.java b/src/java/com/threerings/whirled/server/AbstractSceneMoveHandler.java new file mode 100644 index 00000000..8783c5c3 --- /dev/null +++ b/src/java/com/threerings/whirled/server/AbstractSceneMoveHandler.java @@ -0,0 +1,90 @@ +// +// $Id$ +// +// Vilya library - tools for developing networked games +// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/vilya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.whirled.server; + +import com.threerings.presents.client.InvocationService; +import com.threerings.presents.data.InvocationMarshaller; +import com.threerings.presents.server.InvocationException; + +import com.threerings.crowd.data.BodyObject; + +import com.threerings.whirled.client.SceneService; +import com.threerings.whirled.data.SceneCodes; + +import com.threerings.whirled.Log; + +/** + * Handles the basics of moving a client into a new scene, which may involve resolution. Takes care + * of annoying edge cases like the client logging off before their target scene is resolved and can + * be extended to handle extra fun stuff. + */ +public abstract class AbstractSceneMoveHandler + implements SceneRegistry.ResolutionListener +{ + public AbstractSceneMoveHandler (BodyObject body, int sceneId, int version, + InvocationService.InvocationListener listener) + { + _body = body; + _sceneId = sceneId; + _version = version; + _listener = listener; + } + + // from interface SceneRegistry.ResolutionListener + public void sceneWasResolved (SceneManager scmgr) + { + // make sure our caller is still around; under heavy load, clients might end their session + // while the scene is resolving + if (!_body.isActive()) { + Log.info("Abandoning scene move, client gone [who=" + _body.who() + + ", dest=" + scmgr.where() + "]."); + InvocationMarshaller.setNoResponse(_listener); + return; + } + + try { + effectSceneMove(scmgr); + + } catch (InvocationException sfe) { + _listener.requestFailed(sfe.getMessage()); + + } catch (RuntimeException re) { + Log.logStackTrace(re); + _listener.requestFailed(SceneCodes.INTERNAL_ERROR); + } + } + + // from interface SceneRegistry.ResolutionListener + public void sceneFailedToResolve (int sceneId, Exception reason) + { + Log.warning("Unable to resolve scene [sceneid=" + sceneId + ", reason=" + reason + "]."); + _listener.requestFailed(SceneCodes.NO_SUCH_PLACE); + } + + protected abstract void effectSceneMove (SceneManager scmgr) + throws InvocationException; + + protected BodyObject _body; + protected int _sceneId; + protected int _version; + protected InvocationService.InvocationListener _listener; +} diff --git a/src/java/com/threerings/whirled/server/SceneMoveHandler.java b/src/java/com/threerings/whirled/server/SceneMoveHandler.java new file mode 100644 index 00000000..7748f14d --- /dev/null +++ b/src/java/com/threerings/whirled/server/SceneMoveHandler.java @@ -0,0 +1,76 @@ +// +// $Id$ +// +// Vilya library - tools for developing networked games +// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/vilya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.whirled.server; + +import com.threerings.presents.data.InvocationMarshaller; +import com.threerings.presents.server.InvocationException; + +import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.PlaceConfig; +import com.threerings.crowd.server.CrowdServer; + +import com.threerings.whirled.client.SceneService; +import com.threerings.whirled.data.SceneCodes; +import com.threerings.whirled.data.SceneModel; +import com.threerings.whirled.data.SceneUpdate; +import com.threerings.whirled.data.ScenedBodyObject; + +/** + * Handles a simple scene to scene move. + */ +public class SceneMoveHandler extends AbstractSceneMoveHandler +{ + public SceneMoveHandler (BodyObject body, int sceneId, int sceneVer, + SceneService.SceneMoveListener listener) + { + super(body, sceneId, sceneVer, listener); + } + + @Override // from AbstractSceneMoveHandler + protected void effectSceneMove (SceneManager scmgr) + throws InvocationException + { + // move to the place object associated with this scene + int ploid = scmgr.getPlaceObject().getOid(); + PlaceConfig config = CrowdServer.plreg.locprov.moveTo(_body, ploid); + + // now that we've finally moved, we can update the user object with the new scene id + ((ScenedBodyObject)_body).setSceneId(scmgr.getScene().getId()); + + // check to see if they need a newer version of the scene data + SceneService.SceneMoveListener listener = (SceneService.SceneMoveListener)_listener; + SceneModel model = scmgr.getScene().getSceneModel(); + if (_version != model.version) { + SceneUpdate[] updates = null; + if (_version < model.version) { + updates = scmgr.getUpdates(_version); + } + if (updates != null) { + listener.moveSucceededWithUpdates(ploid, config, updates); + } else { + listener.moveSucceededWithScene(ploid, config, model); + } + } else { + listener.moveSucceeded(ploid, config); + } + } +} diff --git a/src/java/com/threerings/whirled/server/SceneRegistry.java b/src/java/com/threerings/whirled/server/SceneRegistry.java index a5eae9ae..1ef2863d 100644 --- a/src/java/com/threerings/whirled/server/SceneRegistry.java +++ b/src/java/com/threerings/whirled/server/SceneRegistry.java @@ -221,72 +221,11 @@ public class SceneRegistry } // from interface SceneService - public void moveTo (ClientObject caller, int sceneId, final int sceneVer, - final SceneService.SceneMoveListener listener) + public void moveTo (ClientObject caller, int sceneId, int sceneVer, + SceneService.SceneMoveListener listener) { - final BodyObject source = (BodyObject)caller; - - // create a callback object to handle the resolution or failed resolution of the scene - SceneRegistry.ResolutionListener rl = null; - rl = new SceneRegistry.ResolutionListener() { - public void sceneWasResolved (SceneManager scmgr) { - // make sure our caller is still around; under heavy load, clients might end their - // session while the scene is resolving - if (!source.isActive()) { - Log.info("Abandoning scene move, client gone [who=" + source.who() + - ", dest=" + scmgr.where() + "]."); - InvocationMarshaller.setNoResponse(listener); - return; - } - finishMoveToRequest(source, scmgr, sceneVer, listener); - } - - public void sceneFailedToResolve (int rsceneId, Exception reason) { - Log.warning("Unable to resolve scene [sceneid=" + rsceneId + - ", reason=" + reason + "]."); - // pretend like the scene doesn't exist to the client - listener.requestFailed(NO_SUCH_PLACE); - } - }; - - // make sure the scene they are headed to is actually loaded into the server - resolveScene(sceneId, rl); - } - - /** - * Moves the supplied body into the supplied (already resolved) scene and informs the supplied - * listener if the move is successful. - * - * @exception InvocationException thrown if a failure occurs attempting to move the user into - * the place associated with the scene. - */ - public void effectSceneMove (BodyObject source, SceneManager scmgr, - int sceneVersion, SceneService.SceneMoveListener listener) - throws InvocationException - { - // move to the place object associated with this scene - int ploid = scmgr.getPlaceObject().getOid(); - PlaceConfig config = CrowdServer.plreg.locprov.moveTo(source, ploid); - - // now that we've finally moved, we can update the user object with the new scene id - ((ScenedBodyObject)source).setSceneId(scmgr.getScene().getId()); - - // check to see if they need a newer version of the scene data - SceneModel model = scmgr.getScene().getSceneModel(); - if (sceneVersion != model.version) { - SceneUpdate[] updates = null; - if (sceneVersion < model.version) { - // try getting updates to bring the client to the right version - updates = scmgr.getUpdates(sceneVersion); - } - if (updates != null) { - listener.moveSucceededWithUpdates(ploid, config, updates); - } else { - listener.moveSucceededWithScene(ploid, config, model); - } - } else { - listener.moveSucceeded(ploid, config); - } + BodyObject body = (BodyObject)caller; + resolveScene(sceneId, new SceneMoveHandler(body, sceneId, sceneVer, listener)); } /** @@ -315,25 +254,6 @@ public class SceneRegistry source.setSceneId(0); } - /** - * This is called after the scene to which we are moving is guaranteed to have been loaded into - * the server. - */ - protected void finishMoveToRequest (BodyObject source, SceneManager scmgr, int sceneVersion, - SceneService.SceneMoveListener listener) - { - try { - effectSceneMove(source, scmgr, sceneVersion, listener); - - } catch (InvocationException sfe) { - listener.requestFailed(sfe.getMessage()); - - } catch (RuntimeException re) { - Log.logStackTrace(re); - listener.requestFailed(INTERNAL_ERROR); - } - } - /** * Called when the scene resolution has completed successfully. */ diff --git a/src/java/com/threerings/whirled/spot/server/SpotProvider.java b/src/java/com/threerings/whirled/spot/server/SpotProvider.java index 85d4add5..fbcf1238 100644 --- a/src/java/com/threerings/whirled/spot/server/SpotProvider.java +++ b/src/java/com/threerings/whirled/spot/server/SpotProvider.java @@ -83,89 +83,37 @@ public class SpotProvider return; } - // avoid cluttering up the method declaration with final keywords - final BodyObject fsource = (BodyObject)caller; - final int fportalId = portalId; - final int fsceneVer = destSceneVer; - final SceneMoveListener flistener = listener; - // obtain the source scene - final SpotSceneManager srcmgr = (SpotSceneManager)_screg.getSceneManager(sceneId); + BodyObject body = (BodyObject)caller; + SpotSceneManager srcmgr = (SpotSceneManager)_screg.getSceneManager(sceneId); if (srcmgr == null) { Log.warning("Traverse portal missing source scene " + - "[user=" + fsource.who() + ", sceneId=" + sceneId + + "[user=" + body.who() + ", sceneId=" + sceneId + ", portalId=" + portalId + "]."); throw new InvocationException(INTERNAL_ERROR); } // obtain the destination scene and location id SpotScene rss = (SpotScene)srcmgr.getScene(); - final Portal fdest = rss.getPortal(portalId); + Portal dest = rss.getPortal(portalId); // give the source scene manager a chance to do access control - String errmsg = srcmgr.mayTraversePortal(fsource, fdest); + String errmsg = srcmgr.mayTraversePortal(body, dest); if (errmsg != null) { throw new InvocationException(errmsg); } // make sure this portal has valid info - if (fdest == null || !fdest.isValid()) { - Log.warning("Traverse portal with invalid portal [user=" + fsource.who() + - ", scene=" + srcmgr.where() + ", pid=" + portalId + ", portal=" + fdest + + if (dest == null || !dest.isValid()) { + Log.warning("Traverse portal with invalid portal [user=" + body.who() + + ", scene=" + srcmgr.where() + ", pid=" + portalId + ", portal=" + dest + ", portals=" + StringUtil.toString(rss.getPortals()) + "]."); throw new InvocationException(NO_SUCH_PORTAL); } // resolve their destination scene - SceneRegistry.ResolutionListener rl = new SceneRegistry.ResolutionListener() { - public void sceneWasResolved (SceneManager scmgr) { - // make sure our caller is still around; under heavy load, clients might end their - // session while the scene is resolving - if (!fsource.isActive()) { - Log.info("Abandoning portal traversal, client gone [who=" + fsource.who() + - ", dest=" + scmgr.where() + "]."); - InvocationMarshaller.setNoResponse(flistener); - return; - } - - // let the source manager know that this guy is departing via the specified portal - srcmgr.willTraversePortal(fsource, fdest); - - SpotSceneManager sscmgr = (SpotSceneManager)scmgr; - finishTraversePortalRequest(fsource, sscmgr, fsceneVer, fdest, flistener); - } - - public void sceneFailedToResolve ( - int rsceneId, Exception reason) { - Log.warning("Unable to resolve target scene [sceneId=" + rsceneId + - ", reason=" + reason + "]."); - // pretend like the scene doesn't exist to the client - flistener.requestFailed(NO_SUCH_PLACE); - } - }; - _screg.resolveScene(fdest.targetSceneId, rl); - } - - /** - * This is called after the scene to which we are moving is guaranteed to have been loaded into - * the server. - */ - protected void finishTraversePortalRequest ( - BodyObject source, SpotSceneManager destmgr, int sceneVer, Portal dest, - SceneMoveListener listener) - { - // let the destination scene manager know that we're coming in - destmgr.mapEnteringBody(source, dest); - - try { - // move to the place object associated with this scene - _screg.effectSceneMove(source, destmgr, sceneVer, listener); - } catch (InvocationException sfe) { - listener.requestFailed(sfe.getMessage()); - // and let the destination scene manager know that we're no - // longer coming in - destmgr.clearEnteringBody(source); - } + _screg.resolveScene(dest.targetSceneId, new SpotSceneMoveHandler( + srcmgr, body, sceneId, destSceneVer, dest, listener)); } /** diff --git a/src/java/com/threerings/whirled/spot/server/SpotSceneMoveHandler.java b/src/java/com/threerings/whirled/spot/server/SpotSceneMoveHandler.java new file mode 100644 index 00000000..d4d70288 --- /dev/null +++ b/src/java/com/threerings/whirled/spot/server/SpotSceneMoveHandler.java @@ -0,0 +1,69 @@ +// +// $Id$ +// +// Vilya library - tools for developing networked games +// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/vilya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.whirled.spot.server; + +import com.threerings.presents.server.InvocationException; + +import com.threerings.crowd.data.BodyObject; + +import com.threerings.whirled.client.SceneService; +import com.threerings.whirled.server.SceneManager; +import com.threerings.whirled.server.SceneMoveHandler; + +import com.threerings.whirled.spot.data.Portal; + +/** + * Moves a player between scenes, accounting for their exit and entry via portals. + */ +public class SpotSceneMoveHandler extends SceneMoveHandler +{ + public SpotSceneMoveHandler (SpotSceneManager srcmgr, BodyObject body, int sceneId, + int sceneVer, Portal dest, SceneService.SceneMoveListener listener) + { + super(body, sceneId, sceneVer, listener); + _srcmgr = srcmgr; + _dest = dest; + } + + @Override // from AbstractSceneMoveHandler + protected void effectSceneMove (SceneManager scmgr) + throws InvocationException + { + // let the source manager know that this guy is departing via the specified portal + _srcmgr.willTraversePortal(_body, _dest); + + // let the destination scene manager know that we're coming in + SpotSceneManager destmgr = (SpotSceneManager)scmgr; + destmgr.mapEnteringBody(_body, _dest); + + try { + super.effectSceneMove(destmgr); + } catch (InvocationException ie) { + // if anything goes haywire, clear out our entering status + destmgr.clearEnteringBody(_body); + throw ie; + } + } + + protected SpotSceneManager _srcmgr; + protected Portal _dest; +} diff --git a/src/java/com/threerings/whirled/zone/client/ZoneService.java b/src/java/com/threerings/whirled/zone/client/ZoneService.java index 9942da3b..fa202170 100644 --- a/src/java/com/threerings/whirled/zone/client/ZoneService.java +++ b/src/java/com/threerings/whirled/zone/client/ZoneService.java @@ -31,37 +31,30 @@ import com.threerings.whirled.data.SceneUpdate; import com.threerings.whirled.zone.data.ZoneSummary; /** - * Defines the client interface to the zone related invocation services - * (e.g. moving between zones). + * The client interface for zone related invocation services (e.g. moving between zones). */ public interface ZoneService extends InvocationService { /** Used to deliver responses to {@link #moveTo} requests. */ public static interface ZoneMoveListener extends InvocationListener { - public void moveSucceeded ( - int placeId, PlaceConfig config, ZoneSummary summary); + public void moveSucceeded (int placeId, PlaceConfig config, ZoneSummary summary); public void moveSucceededWithUpdates ( - int placeId, PlaceConfig config, ZoneSummary summary, - SceneUpdate[] updates); + int placeId, PlaceConfig config, ZoneSummary summary, SceneUpdate[] updates); public void moveSucceededWithScene ( - int placeId, PlaceConfig config, ZoneSummary summary, - SceneModel model); + int placeId, PlaceConfig config, ZoneSummary summary, SceneModel model); } /** - * Requests that that this client's body be moved to the specified - * scene in the specified zone. + * Requests that that this client's body be moved to the specified scene in the specified zone. * * @param zoneId the zone id to which we want to move. * @param sceneId the scene id to which we want to move. - * @param version the version number of the scene object that we have - * in our local repository. - * @param listener the object that will receive the callback when the - * request succeeds or fails. + * @param version the version number of the scene object that we have in our local repository. + * @param listener receives the callback when the request succeeds or fails. */ - public void moveTo (Client client, int zoneId, int sceneId, - int version, ZoneMoveListener listener); + public void moveTo (Client client, int zoneId, int sceneId, int version, + ZoneMoveListener listener); } diff --git a/src/java/com/threerings/whirled/zone/server/ZoneMoveHandler.java b/src/java/com/threerings/whirled/zone/server/ZoneMoveHandler.java new file mode 100644 index 00000000..d1495640 --- /dev/null +++ b/src/java/com/threerings/whirled/zone/server/ZoneMoveHandler.java @@ -0,0 +1,117 @@ +// +// $Id$ +// +// Vilya library - tools for developing networked games +// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/vilya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.whirled.zone.server; + +import com.threerings.presents.server.InvocationException; + +import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.PlaceConfig; + +import com.threerings.whirled.client.SceneService; +import com.threerings.whirled.data.SceneModel; +import com.threerings.whirled.data.SceneUpdate; +import com.threerings.whirled.data.ScenedBodyObject; +import com.threerings.whirled.server.AbstractSceneMoveHandler; +import com.threerings.whirled.server.SceneManager; +import com.threerings.whirled.server.SceneMoveHandler; +import com.threerings.whirled.server.SceneRegistry; +import com.threerings.whirled.server.WhirledServer; + +import com.threerings.whirled.zone.Log; +import com.threerings.whirled.zone.client.ZoneService; +import com.threerings.whirled.zone.data.ZoneCodes; +import com.threerings.whirled.zone.data.ZoneSummary; +import com.threerings.whirled.zone.data.ZonedBodyObject; + +/** + * Handles transitioning between zones. + */ +public class ZoneMoveHandler extends AbstractSceneMoveHandler + implements ZoneManager.ResolutionListener +{ + public ZoneMoveHandler (ZoneManager zmgr, BodyObject body, int sceneId, int sceneVer, + ZoneService.ZoneMoveListener listener) + { + super(body, sceneId, sceneVer, listener); + _zmgr = zmgr; + } + + // from interface ZoneManager.ResolutionListener + public void zoneWasResolved (ZoneSummary summary) + { + // give the zone manager a chance to veto the request + String errmsg = _zmgr.ratifyBodyEntry(_body, summary.zoneId); + if (errmsg != null) { + _listener.requestFailed(errmsg); + return; + } + _summary = summary; + + // now resolve the target scene + WhirledServer.screg.resolveScene(_sceneId, this); + } + + // from interface ZoneManager.ResolutionListener + public void zoneFailedToResolve (int zoneId, Exception reason) + { + Log.warning("Unable to resolve zone [zoneId=" + zoneId + ", reason=" + reason + "]."); + _listener.requestFailed(ZoneCodes.NO_SUCH_ZONE); + } + + @Override // from AbstractSceneMoveHandler + protected void effectSceneMove (SceneManager scmgr) + throws InvocationException + { + // move to the place object associated with this scene + int ploid = scmgr.getPlaceObject().getOid(); + PlaceConfig config = WhirledServer.plreg.locprov.moveTo(_body, ploid); + + // now that we've moved, we can update the user object with the new scene and zone ids + _body.startTransaction(); + try { + ((ScenedBodyObject)_body).setSceneId(scmgr.getScene().getId()); + ((ZonedBodyObject)_body).setZoneId(_summary.zoneId); + } finally { + _body.commitTransaction(); + } + + // check to see if they need a newer version of the scene data + ZoneService.ZoneMoveListener listener = (ZoneService.ZoneMoveListener)_listener; + SceneModel model = scmgr.getScene().getSceneModel(); + if (_version < model.version) { + SceneUpdate[] updates = scmgr.getUpdates(_version); + if (updates != null) { + listener.moveSucceededWithUpdates(ploid, config, _summary, updates); + } else { + listener.moveSucceededWithScene(ploid, config, _summary, model); + } + } else { + listener.moveSucceeded(ploid, config, _summary); + } + + // let the zone manager know that someone just came on in + _zmgr.bodyDidEnterZone(_body, _summary.zoneId); + } + + protected ZoneManager _zmgr; + protected ZoneSummary _summary; +} diff --git a/src/java/com/threerings/whirled/zone/server/ZoneProvider.java b/src/java/com/threerings/whirled/zone/server/ZoneProvider.java index 8bbf395b..223b613b 100644 --- a/src/java/com/threerings/whirled/zone/server/ZoneProvider.java +++ b/src/java/com/threerings/whirled/zone/server/ZoneProvider.java @@ -44,20 +44,17 @@ import com.threerings.whirled.zone.data.ZoneSummary; import com.threerings.whirled.zone.data.ZonedBodyObject; /** - * Provides zone related services which are presently the ability to move - * from zone to zone. + * Provides zone related services which are presently the ability to move from zone to zone. */ public class ZoneProvider implements ZoneCodes, InvocationProvider { /** - * Constructs a zone provider that will interoperate with the supplied - * zone and scene registries. The zone provider will automatically be - * constructed and registered by the {@link ZoneRegistry}, which a - * zone-using system must create and initialize in their server. + * Constructs a zone provider that will interoperate with the supplied zone and scene + * registries. The zone provider will automatically be constructed and registered by the {@link + * ZoneRegistry}, which a zone-using system must create and initialize in their server. */ - public ZoneProvider (LocationProvider locprov, ZoneRegistry zonereg, - SceneRegistry screg) + public ZoneProvider (LocationProvider locprov, ZoneRegistry zonereg, SceneRegistry screg) { _locprov = locprov; _zonereg = zonereg; @@ -70,31 +67,25 @@ public class ZoneProvider * @param caller the user requesting the move. * @param zoneId the qualified zone id of the new zone. * @param sceneId the identifier of the new scene. - * @param sceneVer the version of the scene model currently held by - * the client. + * @param sceneVer the version of the scene model currently held by the client. * @param listener the entity to inform of success or failure. */ public void moveTo (ClientObject caller, int zoneId, int sceneId, int sceneVer, ZoneMoveListener listener) throws InvocationException { - // avoid cluttering up the method declaration with final keywords - final BodyObject fsource = (BodyObject)caller; - final int fsceneId = sceneId; - final int fsceneVer = sceneVer; - final ZoneMoveListener flistener = listener; - - // look up the caller's current zone id and make sure it is happy - // about their departure from the current zone if (!(caller instanceof ZonedBodyObject)) { - Log.warning("Request to switch zones by non-ZonedBodyObject!? " + + Log.warning("Request to switch zones by non-ZonedBodyObject " + "[clobj=" + caller.getClass() + "]."); throw new InvocationException(INTERNAL_ERROR); } - ZonedBodyObject zcaller = (ZonedBodyObject)caller; - ZoneManager ozmgr = _zonereg.getZoneManager(zcaller.getZoneId()); + + // look up the caller's current zone id and make sure it is happy about their departure + // from the current zone + BodyObject body = (BodyObject)caller; + ZoneManager ozmgr = _zonereg.getZoneManager(((ZonedBodyObject)caller).getZoneId()); if (ozmgr != null) { - String msg = ozmgr.ratifyBodyExit(fsource); + String msg = ozmgr.ratifyBodyExit(body); if (msg != null) { throw new InvocationException(msg); } @@ -103,146 +94,23 @@ public class ZoneProvider // look up the zone manager for the zone ZoneManager zmgr = _zonereg.getZoneManager(zoneId); if (zmgr == null) { - Log.warning("Requested to enter a zone for which we have no " + - "manager [user=" + fsource.who() + - ", zoneId=" + zoneId + "]."); + Log.warning("Requested to enter a zone for which we have no manager " + + "[user=" + body.who() + ", zoneId=" + zoneId + "]."); throw new InvocationException(NO_SUCH_ZONE); } - // resolve the zone! - ZoneManager.ResolutionListener zl = new ZoneManager.ResolutionListener() - { - public void zoneWasResolved (ZoneSummary summary) { - continueMoveTo( - fsource, summary, fsceneId, fsceneVer, flistener); - } - - public void zoneFailedToResolve (int zoneId, Exception reason) { - Log.warning("Unable to resolve zone [zoneId=" + zoneId + - ", reason=" + reason + "]."); - flistener.requestFailed(NO_SUCH_ZONE); - } - }; - zmgr.resolveZone(zoneId, zl); + // resolve the zone and move the user + zmgr.resolveZone(zoneId, new ZoneMoveHandler( + zmgr, (BodyObject)caller, sceneId, sceneVer, listener)); } /** - * This is called after we have resolved our zone. - */ - protected void continueMoveTo ( - BodyObject source, ZoneSummary summary, int sceneId, int sceneVer, - ZoneMoveListener listener) - { - // avoid cluttering up the method declaration with final keywords - final BodyObject fsource = source; - final ZoneSummary fsum = summary; - final int fsceneVer = sceneVer; - final ZoneMoveListener flistener = listener; - - // give the zone manager a chance to veto the request - ZoneManager zmgr = _zonereg.getZoneManager(summary.zoneId); - String errmsg = zmgr.ratifyBodyEntry(source, summary.zoneId); - if (errmsg != null) { - listener.requestFailed(errmsg); - return; - } - - // create a callback object that will handle the resolution or - // failed resolution of the scene - SceneRegistry.ResolutionListener rl = null; - rl = new SceneRegistry.ResolutionListener() { - public void sceneWasResolved (SceneManager scmgr) { - // make sure our caller is still around; under heavy load, - // clients might end their session while the scene is - // resolving - if (!fsource.isActive()) { - Log.info("Abandoning zone move, client gone " + - "[who=" + fsource.who() + - ", dest=" + scmgr.where() + "]."); - // No one to respond to, just mark that we're okay with it. - InvocationMarshaller.setNoResponse(flistener); - return; - } - finishMoveTo(fsource, fsum, scmgr, fsceneVer, flistener); - } - - public void sceneFailedToResolve (int sceneId, Exception reason) { - Log.warning("Unable to resolve scene [sceneid=" + sceneId + - ", reason=" + reason + "]."); - // pretend like the scene doesn't exist to the client - flistener.requestFailed(NO_SUCH_PLACE); - } - }; - - // make sure the scene they are headed to is actually loaded into - // the server - _screg.resolveScene(sceneId, rl); - } - - /** - * This is called after the scene to which we are moving is guaranteed - * to have been loaded into the server. - */ - protected void finishMoveTo ( - BodyObject source, ZoneSummary summary, SceneManager scmgr, - int sceneVersion, ZoneMoveListener listener) - { - // move to the place object associated with this scene - PlaceObject plobj = scmgr.getPlaceObject(); - int ploid = plobj.getOid(); - - try { - // try doing the actual move - PlaceConfig config = _locprov.moveTo(source, ploid); - - // now that we've finally moved, we can update the user object - // with the new scene and zone ids - source.startTransaction(); - try { - ((ScenedBodyObject)source).setSceneId(scmgr.getScene().getId()); - ((ZonedBodyObject)source).setZoneId(summary.zoneId); - } finally { - source.commitTransaction(); - } - - // check to see if they need a newer version of the scene data - SceneModel model = scmgr.getScene().getSceneModel(); - if (sceneVersion < model.version) { - SceneUpdate[] updates = scmgr.getUpdates(sceneVersion); - if (updates != null) { - listener.moveSucceededWithUpdates( - ploid, config, summary, updates); - } else { - listener.moveSucceededWithScene( - ploid, config, summary, model); - } - - } else { - // then send the moveTo response - listener.moveSucceeded(ploid, config, summary); - } - - // let the zone manager know that someone just came on in - ZoneManager zmgr = _zonereg.getZoneManager(summary.zoneId); - zmgr.bodyDidEnterZone(source, summary.zoneId); - - } catch (InvocationException ie) { - listener.requestFailed(ie.getMessage()); - - } catch (RuntimeException re) { - Log.logStackTrace(re); - listener.requestFailed(INTERNAL_ERROR); - } - } - - /** - * 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}. + * 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}. * - * @return null if the user was forcibly moved, or a string indicating - * the reason for denial of departure of their current zone (from - * {@link ZoneManager#ratifyBodyExit}). + * @return null if the user was forcibly moved, or a string indicating the reason for denial of + * departure of their current zone (from {@link ZoneManager#ratifyBodyExit}). */ public String moveBody (ZonedBodyObject source, int zoneId, int sceneId) { @@ -264,18 +132,16 @@ public class ZoneProvider } /** - * Ejects the specified body from their current scene and zone. This - * is the zone equivalent to {@link - * LocationProvider#leaveOccupiedPlace}. + * Ejects the specified body from their current scene and zone. This is the zone equivalent to + * {@link LocationProvider#leaveOccupiedPlace}. * - * @return null if the user was forcibly moved, or a string indicating - * the reason for denial of departure of their current zone (from - * {@link ZoneManager#ratifyBodyExit}). + * @return null if the user was forcibly moved, or a string indicating the reason for denial of + * departure of their current zone (from {@link ZoneManager#ratifyBodyExit}). */ public String leaveOccupiedZone (ZonedBodyObject source) { - // look up the caller's current zone id and make sure it is happy - // about their departure from the current zone + // look up the caller's current zone id and make sure it is happy about their departure + // from the current zone ZoneManager zmgr = _zonereg.getZoneManager(source.getZoneId()); String msg; if (zmgr != null &&