From 7af21e2aa0fb2f303d468e2a93e6d4c9ea7c33d6 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Tue, 30 Nov 2010 16:38:38 +0000 Subject: [PATCH] Recent server-side work has tried to evolve away from the assumption that the ClientObject you log in with is necessarily the BodyObject you drive around the world. This client-side commit matches the new BodyLocator.forClient() method on the server by the addition of CrowdClient.bodyOf(), which should be subclassed by anyone who wants to do anything fancy. The default implementation is just for the client to cast itself to BodyObject, matching the default (and historical) implementation in BodyLocator. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6317 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../crowd/chat/client/ChatDirector.as | 49 +++++++++++++------ .../crowd/chat/client/TellHandler.as | 6 +-- .../threerings/crowd/client/CrowdClient.as | 11 +++++ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/main/as/com/threerings/crowd/chat/client/ChatDirector.as b/src/main/as/com/threerings/crowd/chat/client/ChatDirector.as index b1d2474e6..40915ba31 100644 --- a/src/main/as/com/threerings/crowd/chat/client/ChatDirector.as +++ b/src/main/as/com/threerings/crowd/chat/client/ChatDirector.as @@ -20,7 +20,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package com.threerings.crowd.chat.client { - +import com.threerings.crowd.client.CrowdClient; import com.threerings.util.ArrayUtil; import com.threerings.util.Log; import com.threerings.util.Map; @@ -33,7 +33,6 @@ import com.threerings.presents.client.BasicDirector; import com.threerings.presents.client.Client; import com.threerings.presents.client.ClientEvent; import com.threerings.presents.client.InvocationAdapter; -import com.threerings.presents.data.ClientObject; import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.MessageEvent; import com.threerings.presents.dobj.MessageListener; @@ -68,6 +67,16 @@ public class ChatDirector extends BasicDirector // statically reference classes we require ChatMarshaller; + /** + * Convenience method for returning the body of a client in a super safe manner, taking + * into account the (remote, one imagines) possibility that it might not be a CrowdClient. + */ + public static function getBodyObject (client :Client) :BodyObject + { + return (client is CrowdClient) ? (client as CrowdClient).bodyOf() : + (client.getClientObject() as BodyObject); + } + /** * Creates a chat director and initializes it with the supplied context. * @@ -452,10 +461,10 @@ public class ChatDirector extends BasicDirector * @param target the username of the user to which the tell message should be delivered. * @param msg the contents of the tell message. * @param rl an optional result listener if you'd like to be notified of success or failure. - * @param feedbackLocaltype this local type will be used for both TellFeedbackMessages, and + * @param feedbackLocaltype this local type will be used for both TellFeedbackMessages, and * regular feedback that is dispatched for away/idle messages. */ - public function requestTell (target :Name, msg :String, rl :ResultListener, + public function requestTell (target :Name, msg :String, rl :ResultListener, feedbackLocaltype :String = ChatCodes.PLACE_CHAT_TYPE) :void { // make sure they can say what they want to say @@ -615,8 +624,10 @@ public class ChatDirector extends BasicDirector { super.clientDidLogon(event); - // listen on the client object for tells - addAuxiliarySource(_clobj = event.getClient().getClientObject(), ChatCodes.USER_CHAT_TYPE); + _auxobj = getBodyObject(event.getClient()); + + // listen on the body object for tells + addAuxiliarySource(_auxobj, ChatCodes.USER_CHAT_TYPE); } // documentation inherited @@ -625,8 +636,13 @@ public class ChatDirector extends BasicDirector super.clientObjectDidChange(event); // change what we're listening to for tells - removeAuxiliarySource(_clobj); - addAuxiliarySource(_clobj = event.getClient().getClientObject(), ChatCodes.USER_CHAT_TYPE); + if (_auxobj != null) { + removeAuxiliarySource(_auxobj); + } + _auxobj = getBodyObject(event.getClient()); + + // listen on the body object for tells + addAuxiliarySource(_auxobj, ChatCodes.USER_CHAT_TYPE); if (clearChatOnClientExit()) { clearDisplays(); @@ -638,11 +654,12 @@ public class ChatDirector extends BasicDirector { super.clientDidLogoff(event); - // stop listening to it for tells - if (_clobj != null) { - removeAuxiliarySource(_clobj); - _clobj = null; + if (_auxobj != null) { + // stop listening to it for tells + removeAuxiliarySource(_auxobj); + _auxobj = null; } + // in fact, clear out all auxiliary sources _auxes.clear(); @@ -699,7 +716,7 @@ public class ChatDirector extends BasicDirector addChatter(speaker); // note whether or not we have an auto-response - var self :BodyObject = (_cctx.getClient().getClientObject() as BodyObject); + var self :BodyObject = getBodyObject(_cctx.getClient()); if (!StringUtil.isBlank(self.awayMessage)) { autoResponse = self.awayMessage; } @@ -915,7 +932,7 @@ public class ChatDirector extends BasicDirector internal function getCommandHandlers (command :String) :Map { var matches :Map = Maps.newMapOf(String); - var user :BodyObject = (_cctx.getClient().getClientObject() as BodyObject); + var user :BodyObject = getBodyObject(_cctx.getClient()); var keys :Array = _handlers.keys(); for (var ii :int = 0; ii < keys.length; ii++) { var cmd :String = (keys[ii] as String); @@ -1046,8 +1063,8 @@ public class ChatDirector extends BasicDirector /** The place object that we currently occupy. */ protected var _place :PlaceObject; - /** The client object that we're listening to for tells. */ - protected var _clobj :ClientObject; + /** The object that we're listening to for tells. */ + protected var _auxobj :DObject; /** A list of registered chat displays. */ protected var _displays :ObserverList = new ObserverList(); diff --git a/src/main/as/com/threerings/crowd/chat/client/TellHandler.as b/src/main/as/com/threerings/crowd/chat/client/TellHandler.as index f0cadf507..ce40d740e 100644 --- a/src/main/as/com/threerings/crowd/chat/client/TellHandler.as +++ b/src/main/as/com/threerings/crowd/chat/client/TellHandler.as @@ -53,10 +53,8 @@ public class TellHandler extends CommandHandler } // make sure we're not trying to tell something to ourselves - var self :BodyObject = - (ctx.getClient().getClientObject() as BodyObject); - if (handle.toLowerCase() === - self.getVisibleName().toString().toLowerCase()) { + var self :BodyObject = ChatDirector.getBodyObject(ctx.getClient()); + if (handle.toLowerCase() === self.getVisibleName().toString().toLowerCase()) { return "m.talk_self"; } diff --git a/src/main/as/com/threerings/crowd/client/CrowdClient.as b/src/main/as/com/threerings/crowd/client/CrowdClient.as index 892bdc6e2..0aeb853b6 100644 --- a/src/main/as/com/threerings/crowd/client/CrowdClient.as +++ b/src/main/as/com/threerings/crowd/client/CrowdClient.as @@ -25,6 +25,7 @@ import com.threerings.presents.client.Client; import com.threerings.presents.net.Credentials; import com.threerings.crowd.data.BodyMarshaller; +import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.CrowdPermissionPolicy; /** @@ -42,5 +43,15 @@ public class CrowdClient extends Client { super(creds); } + + /** + * Returns the body this client is (currently) attached to. If you subclass this, its result + * should probably match whatever {@link BodyLocator#forClient} would return for this client. + * The default implements the historical assumption that the client object is also the body. + */ + public function bodyOf () :BodyObject + { + return (getClientObject() as BodyObject); + } } }