From c2fb8f99c74c7af8d094b9fb8d32a82b888b4576 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Tue, 15 May 2007 00:27:07 +0000 Subject: [PATCH] Instead of magically creating the ManagerCaller and using the DObjectManager provided to the object when it was created, have the LocationDirector initialize the manager caller when it receives the PlaceObject and have it use its client distributed object manager which tags events with the proper clientOid. This still prevents us from running multiple clients in the same VM, so this will probably all have to change again but this works for now. Also some widening. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4712 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../crowd/client/LocationDirector.java | 242 ++++++++---------- .../threerings/crowd/data/PlaceObject.java | 55 ++-- 2 files changed, 136 insertions(+), 161 deletions(-) diff --git a/src/java/com/threerings/crowd/client/LocationDirector.java b/src/java/com/threerings/crowd/client/LocationDirector.java index 3fac15a4d..c5564179f 100644 --- a/src/java/com/threerings/crowd/client/LocationDirector.java +++ b/src/java/com/threerings/crowd/client/LocationDirector.java @@ -41,33 +41,31 @@ import com.threerings.crowd.data.PlaceObject; import com.threerings.crowd.util.CrowdContext; /** - * The location director provides a means by which entities on the client - * can request to move from place to place and can be notified if other - * entities have caused the client to move to a new place. It also - * provides a mechanism for ratifying a request to move to a new place - * before actually issuing the request. + * The location director provides a means by which entities on the client can request to move from + * place to place and can be notified if other entities have caused the client to move to a new + * place. It also provides a mechanism for ratifying a request to move to a new place before + * actually issuing the request. */ public class LocationDirector extends BasicDirector implements LocationCodes, Subscriber, LocationReceiver, LocationService.MoveListener { /** - * Used to recover from a moveTo request that was accepted but - * resulted in a failed attempt to fetch the place object to which we - * were moving. + * Used to recover from a moveTo request that was accepted but resulted in a failed attempt to + * fetch the place object to which we were moving. */ public static interface FailureHandler { /** - * Should instruct the client to move to the last known working - * location (as well as clean up after the failed moveTo request). + * Should instruct the client to move to the last known working location (as well as clean + * up after the failed moveTo request). */ public void recoverFailedMove (int placeId); } /** - * Constructs a location director which will configure itself for - * operation using the supplied context. + * Constructs a location director which will configure itself for operation using the supplied + * context. */ public LocationDirector (CrowdContext ctx) { @@ -77,14 +75,12 @@ public class LocationDirector extends BasicDirector _ctx = ctx; // register for location notifications - _ctx.getClient().getInvocationDirector().registerReceiver( - new LocationDecoder(this)); + _ctx.getClient().getInvocationDirector().registerReceiver(new LocationDecoder(this)); } /** - * Adds a location observer to the list. This observer will - * subsequently be notified of potential, effected and failed location - * changes. + * Adds a location observer to the list. This observer will subsequently be notified of + * potential, effected and failed location changes. */ public void addLocationObserver (LocationObserver observer) { @@ -100,8 +96,8 @@ public class LocationDirector extends BasicDirector } /** - * Returns the place object for the location we currently occupy or - * null if we're not currently occupying any location. + * Returns the place object for the location we currently occupy or null if we're not currently + * occupying any location. */ public PlaceObject getPlaceObject () { @@ -117,13 +113,11 @@ public class LocationDirector extends BasicDirector } /** - * Requests that this client be moved to the specified place. A - * request will be made and when the response is received, the - * location observers will be notified of success or failure. + * Requests that this client be moved to the specified place. A request will be made and when + * the response is received, the location observers will be notified of success or failure. * - * @return true if the move to request was issued, false if it was - * rejected by a location observer or because we have another request - * outstanding. + * @return true if the move to request was issued, false if it was rejected by a location + * observer or because we have another request outstanding. */ public boolean moveTo (int placeId) { @@ -133,31 +127,26 @@ public class LocationDirector extends BasicDirector return false; } - // first check to see if our observers are happy with this move - // request + // first check to see if our observers are happy with this move request if (!mayMoveTo(placeId, null)) { return false; } - // we need to call this both to mark that we're issuing a move - // request and to check to see if the last issued request should - // be considered stale + // we need to call this both to mark that we're issuing a move request and to check to see + // if the last issued request should be considered stale boolean refuse = checkRepeatMove(); // complain if we're over-writing a pending request if (_pendingPlaceId != -1) { - // if the pending request has been outstanding more than a - // minute, go ahead and let this new one through in an attempt - // to recover from dropped moveTo requests + // if the pending request has been outstanding more than a minute, go ahead and let + // this new one through in an attempt to recover from dropped moveTo requests if (refuse) { Log.warning("Refusing moveTo; We have a request outstanding " + - "[ppid=" + _pendingPlaceId + - ", npid=" + placeId + "]."); + "[ppid=" + _pendingPlaceId + ", npid=" + placeId + "]."); return false; } else { - Log.warning("Overriding stale moveTo request " + - "[ppid=" + _pendingPlaceId + + Log.warning("Overriding stale moveTo request [ppid=" + _pendingPlaceId + ", npid=" + placeId + "]."); } } @@ -172,11 +161,10 @@ public class LocationDirector extends BasicDirector } /** - * Requests to move to the room that we last occupied, if such a room - * exists. + * Requests to move to the room that we last occupied, if such a room exists. * - * @return true if we had a previous room and we requested to move to - * it, false if we had no previous room. + * @return true if we had a previous room and we requested to move to it, false if we had no + * previous room. */ public boolean moveBack () { @@ -192,8 +180,8 @@ public class LocationDirector extends BasicDirector /** * Issues a request to leave our current location. * - * @return true if we were able to leave, false if we are in the - * middle of moving somewhere and can't yet leave. + * @return true if we were able to leave, false if we are in the middle of moving somewhere and + * can't yet leave. */ public boolean leavePlace () { @@ -207,16 +195,15 @@ public class LocationDirector extends BasicDirector } /** - * This can be called by cooperating directors that need to coopt the - * moving process to extend it in some way or other. In such - * situations, they should call this method before moving to a new - * location to check to be sure that all of the registered location - * observers are amenable to a location change. + * This can be called by cooperating directors that need to coopt the moving process to extend + * it in some way or other. In such situations, they should call this method before moving to a + * new location to check to be sure that all of the registered location observers are amenable + * to a location change. * * @param placeId the place oid of our tentative new location. * - * @return true if everyone is happy with the move, false if it was - * vetoed by one of the location observers. + * @return true if everyone is happy with the move, false if it was vetoed by one of the + * location observers. */ public boolean mayMoveTo (final int placeId, ResultListener rl) { @@ -228,12 +215,11 @@ public class LocationDirector extends BasicDirector } }); - // if we're actually going somewhere, let the controller know that - // we might be leaving + // if we're actually going somewhere, let the controller know that we might be leaving mayLeavePlace(); - // if we have a result listener, let it know if we failed - // or keep it for later if we're still going + // if we have a result listener, let it know if we failed or keep it for later if we're + // still going if (rl != null) { if (vetoed[0]) { rl.requestFailed(new MoveVetoedException()); @@ -246,8 +232,7 @@ public class LocationDirector extends BasicDirector } /** - * Called to inform our controller that we may be leaving the current - * place. + * Called to inform our controller that we may be leaving the current place. */ protected void mayLeavePlace () { @@ -255,19 +240,17 @@ public class LocationDirector extends BasicDirector try { _controller.mayLeavePlace(_plobj); } catch (Exception e) { - Log.warning("Place controller choked in " + - "mayLeavePlace [plobj=" + _plobj + "]."); + Log.warning("Place controller choked in mayLeavePlace [plobj=" + _plobj + "]."); Log.logStackTrace(e); } } } /** - * This can be called by cooperating directors that need to coopt the - * moving process to extend it in some way or other. In such - * situations, they will be responsible for receiving the successful - * move response and they should let the location director know that - * the move has been effected. + * This can be called by cooperating directors that need to coopt the moving process to extend + * it in some way or other. In such situations, they will be responsible for receiving the + * successful move response and they should let the location director know that the move has + * been effected. * * @param placeId the place oid of our new location. * @param config the configuration information for the new place. @@ -294,8 +277,7 @@ public class LocationDirector extends BasicDirector // start up a new place controller to manage the new place _controller = createController(config); if (_controller == null) { - Log.warning("Place config returned null controller " + - "[config=" + config + "]."); + Log.warning("Place config returned null controller [config=" + config + "]."); return; } _controller.init(_ctx, config); @@ -305,9 +287,8 @@ public class LocationDirector extends BasicDirector } /** - * 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 + * 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. */ public void didLeavePlace () @@ -318,16 +299,14 @@ public class LocationDirector extends BasicDirector try { _controller.didLeavePlace(_plobj); } catch (Exception e) { - Log.warning("Place controller choked in " + - "didLeavePlace [plobj=" + _plobj + "]."); + Log.warning("Place controller choked in didLeavePlace [plobj=" + _plobj + "]."); Log.logStackTrace(e); } _controller = null; } // unsubscribe from our old place object - _ctx.getDObjectManager().unsubscribeFromObject( - _plobj.getOid(), this); + _ctx.getDObjectManager().unsubscribeFromObject(_plobj.getOid(), this); _plobj = null; // and clear out the associated place id @@ -336,10 +315,9 @@ public class LocationDirector extends BasicDirector } /** - * This can be called by cooperating directors that need to coopt the - * moving process to extend it in some way or other. If the coopted - * move request fails, this failure can be propagated to the location - * observers if appropriate. + * This can be called by cooperating directors that need to coopt the moving process to extend + * it in some way or other. If the coopted move request fails, this failure can be propagated + * to the location observers if appropriate. * * @param placeId the place oid to which we failed to move. * @param reason the reason code given for failure. @@ -359,8 +337,8 @@ public class LocationDirector extends BasicDirector } /** - * Called to test and set a time stamp that we use to determine if a - * pending moveTo request is stale. + * Called to test and set a time stamp that we use to determine if a pending moveTo request is + * stale. */ public boolean checkRepeatMove () { @@ -381,16 +359,12 @@ public class LocationDirector extends BasicDirector // subscribe to our body object Subscriber sub = new Subscriber() { - public void objectAvailable (BodyObject object) - { + public void objectAvailable (BodyObject object) { gotBodyObject(object); } - - public void requestFailed (int oid, ObjectAccessException cause) - { - Log.warning("Location director unable to fetch body " + - "object; all has gone horribly wrong" + - "[cause=" + cause + "]."); + public void requestFailed (int oid, ObjectAccessException cause) { + Log.warning("Location director unable to fetch body object; all has gone " + + "horribly wrong [cause=" + cause + "]."); } }; int cloid = client.getClientOid(); @@ -409,8 +383,8 @@ public class LocationDirector extends BasicDirector // let our observers know that we're no longer in a location _observers.apply(_didChangeOp); - // clear out everything else (it's possible that we were logged - // off in the middle of a change location request) + // clear out everything else (it's possible that we were logged off in the middle of a + // change location request) _pendingPlaceId = -1; _previousPlaceId = -1; _lastRequestTime = 0L; @@ -432,8 +406,8 @@ public class LocationDirector extends BasicDirector protected void gotBodyObject (BodyObject clobj) { - // check to see if we are already in a location, in which case - // we'll want to be going there straight away + // TODO? check to see if we are already in a location, in which case we'll want to be going + // there straight away } // documentation inherited from interface @@ -453,8 +427,7 @@ public class LocationDirector extends BasicDirector int placeId = _pendingPlaceId; _pendingPlaceId = -1; - Log.info("moveTo failed [pid=" + placeId + - ", reason=" + reason + "]."); + Log.info("moveTo failed [pid=" + placeId + ", reason=" + reason + "]."); // let our observers know that something has gone horribly awry notifyFailure(placeId, reason); @@ -476,21 +449,23 @@ public class LocationDirector extends BasicDirector } /** - * Called when we receive the place object to which we subscribed - * after a successful moveTo request. + * Called when we receive the place object to which we subscribed after a successful moveTo + * request. */ public void objectAvailable (PlaceObject object) { // yay, we have our new place object _plobj = object; + // fill in our manager caller + _plobj.initManagerCaller(_ctx.getClient().getDObjectManager()); + // let the place controller know that we're ready to roll if (_controller != null) { try { _controller.willEnterPlace(_plobj); } catch (Exception e) { - Log.warning("Controller choked in willEnterPlace " + - "[place=" + _plobj + "]."); + Log.warning("Controller choked in willEnterPlace [place=" + _plobj + "]."); Log.logStackTrace(e); } } @@ -500,17 +475,15 @@ public class LocationDirector extends BasicDirector } /** - * Called if we are unable to subscribe to the place object that was - * provided to us with our successful moveTo request. This is - * generally a bad scene and we do our best to recover by going back - * to the previously known location. + * Called if we are unable to subscribe to the place object that was provided to us with our + * successful moveTo request. This is generally a bad scene and we do our best to recover by + * going back to the previously known location. */ public void requestFailed (int oid, ObjectAccessException cause) { - // aiya! we were unable to fetch our new place object; something - // is badly wrong - Log.warning("Aiya! Unable to fetch place object for new location " + - "[plid=" + oid + ", reason=" + cause + "]."); + // aiya! we were unable to fetch our new place object; something is badly wrong + Log.warning("Aiya! Unable to fetch place object for new location [plid=" + oid + + ", reason=" + cause + "]."); // clear out our half initialized place info int placeId = _placeId; @@ -519,9 +492,8 @@ public class LocationDirector extends BasicDirector // let the kids know shit be fucked notifyFailure(placeId, "m.unable_to_fetch_place_object"); - // we need to sort out what to do about the half-initialized place - // controller. presently we punt and hope that calling - // didLeavePlace() without ever having called willEnterPlace() + // we need to sort out what to do about the half-initialized place controller. presently we + // punt and hope that calling didLeavePlace() without ever having called willEnterPlace() // does whatever's necessary // try to return to our previous location @@ -529,9 +501,8 @@ public class LocationDirector extends BasicDirector _failureHandler.recoverFailedMove(placeId); } else { - // if we were previously somewhere (and that somewhere isn't - // where we just tried to go), try going back to that happy - // place + // if we were previously somewhere (and that somewhere isn't where we just tried to + // go), try going back to that happy place if (_previousPlaceId != -1 && _previousPlaceId != placeId) { moveTo(_previousPlaceId); } @@ -539,23 +510,20 @@ public class LocationDirector extends BasicDirector } /** - * Sets the failure handler which will recover from place object - * fetching failures. In the event that we are unable to fetch our - * place object after making a successful moveTo request, we attempt - * to rectify the failure by moving back to the last known working - * location. Because entites that cooperate with the location director - * may need to become involved in this failure recovery, we provide - * this interface whereby they can interject themseves into the + * Sets the failure handler which will recover from place object fetching failures. In the + * event that we are unable to fetch our place object after making a successful moveTo request, + * we attempt to rectify the failure by moving back to the last known working location. Because + * entites that cooperate with the location director may need to become involved in this + * failure recovery, we provide this interface whereby they can interject themseves into the * failure recovery process and do their own failure recovery. */ public void setFailureHandler (FailureHandler handler) { if (_failureHandler != null) { - Log.warning("Requested to set failure handler, but we've " + - "already got one. The conflicting entities will " + - "likely need to perform more sophisticated " + - "coordination to deal with failures. " + - "[old=" + _failureHandler + ", new=" + handler + "]."); + Log.warning("Requested to set failure handler, but we've already got one. The " + + "conflicting entities will likely need to perform more sophisticated " + + "coordination to deal with failures. [old=" + _failureHandler + + ", new=" + handler + "]."); } else { _failureHandler = handler; @@ -573,10 +541,9 @@ public class LocationDirector extends BasicDirector } /** - * Called to create our place controller using the supplied place - * configuration. This lives in a separate method so that derived instances - * can do funny class loader business if necessary to load the place - * controller using a sandboxed class loader. + * Called to create our place controller using the supplied place configuration. This lives in + * a separate method so that derived instances can do funny class loader business if necessary + * to load the place controller using a sandboxed class loader. */ protected PlaceController createController (PlaceConfig config) { @@ -590,8 +557,8 @@ public class LocationDirector extends BasicDirector protected LocationService _lservice; /** Our location observer list. */ - protected ObserverList _observers = - new ObserverList(ObserverList.SAFE_IN_ORDER_NOTIFY); + protected ObserverList _observers = new ObserverList( + ObserverList.SAFE_IN_ORDER_NOTIFY); /** The oid of the place we currently occupy. */ protected int _placeId = -1; @@ -602,10 +569,8 @@ public class LocationDirector extends BasicDirector /** The place controller in effect for our current place. */ protected PlaceController _controller; - /** - * The oid of the place for which we have an outstanding moveTo - * request, or -1 if we have no outstanding request. - */ + /** The oid of the place for which we have an outstanding moveTo request, or -1 if we have no + * outstanding request. */ protected int _pendingPlaceId = -1; /** The oid of the place we previously occupied. */ @@ -614,24 +579,21 @@ public class LocationDirector extends BasicDirector /** The last time we requested a move to. */ protected long _lastRequestTime; - /** The entity that deals when we fail to subscribe to a place - * object. */ + /** The entity that deals when we fail to subscribe to a place object. */ protected FailureHandler _failureHandler; - /** A listener that wants to know if we succeeded or - * how we failed to move. */ + /** A listener that wants to know if we succeeded or how we failed to move. */ protected ResultListener _moveListener; /** The operation used to inform observers that the location changed. */ - protected ObserverOp _didChangeOp = - new ObserverOp() { + protected ObserverOp _didChangeOp = new ObserverOp() { public boolean apply (LocationObserver obs) { obs.locationDidChange(_plobj); return true; } }; - /** We require that a moveTo request be outstanding for one minute - * before it is declared to be stale. */ + /** We require that a moveTo request be outstanding for one minute before it is declared to be + * stale. */ protected static final long STALE_REQUEST_DURATION = 60L * 1000L; } diff --git a/src/java/com/threerings/crowd/data/PlaceObject.java b/src/java/com/threerings/crowd/data/PlaceObject.java index 47d9d165f..a8047d06b 100644 --- a/src/java/com/threerings/crowd/data/PlaceObject.java +++ b/src/java/com/threerings/crowd/data/PlaceObject.java @@ -26,6 +26,7 @@ import java.util.Iterator; import com.threerings.util.Name; import com.threerings.presents.dobj.DObject; +import com.threerings.presents.dobj.DObjectManager; import com.threerings.presents.dobj.DSet; import com.threerings.presents.dobj.OidList; import com.threerings.presents.dobj.ServerMessageEvent; @@ -35,10 +36,9 @@ import com.threerings.crowd.chat.data.SpeakMarshaller; import com.threerings.crowd.chat.data.SpeakObject; /** - * A distributed object that contains information on a place that is - * occupied by bodies. This place might be a chat room, a game room, an - * island in a massively multiplayer piratical universe, anything that has - * occupants that might want to chat with one another. + * A distributed object that contains information on a place that is occupied by bodies. This place + * might be a chat room, a game room, an island in a massively multiplayer piratical universe, + * anything that has occupants that might want to chat with one another. */ public class PlaceObject extends DObject implements SpeakObject @@ -55,37 +55,42 @@ public class PlaceObject extends DObject // AUTO-GENERATED: FIELDS END /** - * Exists solely to make calls into the manager look sensible: + * Exists to make calls into the manager look sensible: + * *
_plobj.manager.invoke("someMethod", args);
+ * + * and to route events through the right distributed object manager if we are running in + * standalone/single-player mode where both client and server are running in the same VM. */ public class ManagerCaller { public void invoke (String method, Object ... args) { - postEvent(new ServerMessageEvent(_oid, method, args)); + _omgr.postEvent(new ServerMessageEvent(_oid, method, args)); } + protected ManagerCaller (DObjectManager omgr) { + _omgr = omgr; + } + protected DObjectManager _omgr; } /** * Allows the client to call methods on the manager. */ - public transient ManagerCaller manager = new ManagerCaller(); + public transient ManagerCaller manager; /** - * Tracks the oid of the body objects of all of the occupants of this - * place. + * Tracks the oid of the body objects of all of the occupants of this place. */ public OidList occupants = new OidList(); /** - * Contains an info record (of type {@link OccupantInfo}) for each - * occupant that contains information about that occupant that needs - * to be known by everyone in the place. Note: Don't obtain - * occupant info records directly from this set when on the server, + * Contains an info record (of type {@link OccupantInfo}) for each occupant that contains + * information about that occupant that needs to be known by everyone in the place. + * Note: Don't obtain occupant info records directly from this set when on the server, * use PlaceManager.getOccupantInfo() instead (along with - * PlaceManager.updateOccupantInfo()) because it does - * some special processing to ensure that readers and updaters don't - * step on one another even if they make rapid fire changes to a - * user's occupant info. + * PlaceManager.updateOccupantInfo()) because it does some special processing to + * ensure that readers and updaters don't step on one another even if they make rapid fire + * changes to a user's occupant info. */ public DSet occupantInfo = new DSet(); @@ -93,8 +98,16 @@ public class PlaceObject extends DObject public SpeakMarshaller speakService; /** - * Used to indicate whether broadcast chat messages should be dispatched - * on this place object. + * Called on the client when the location director receives this place object to configure our + * manager caller using the client's distributed object manager. + */ + public void initManagerCaller (DObjectManager omgr) + { + manager = new ManagerCaller(omgr); + } + + /** + * Used to indicate whether broadcast chat messages should be dispatched on this place object. */ public boolean shouldBroadcast () { @@ -104,8 +117,8 @@ public class PlaceObject extends DObject /** * Looks up a user's occupant info by name. * - * @return the occupant info record for the named user or null if no - * user in the room has that username. + * @return the occupant info record for the named user or null if no user in the room has that + * username. */ public OccupantInfo getOccupantInfo (Name username) {