diff --git a/src/java/com/threerings/whirled/spot/client/SpotCodes.java b/src/java/com/threerings/whirled/spot/client/SpotCodes.java index 0c7ee6fa8..0b600e143 100644 --- a/src/java/com/threerings/whirled/spot/client/SpotCodes.java +++ b/src/java/com/threerings/whirled/spot/client/SpotCodes.java @@ -1,5 +1,5 @@ // -// $Id: SpotCodes.java,v 1.2 2001/12/14 23:12:39 mdb Exp $ +// $Id: SpotCodes.java,v 1.3 2001/12/16 21:02:18 mdb Exp $ package com.threerings.whirled.spot.client; @@ -41,6 +41,6 @@ public interface SpotCodes extends ChatCodes, SceneCodes * generated by a failed changeLoc request. */ public static final String LOCATION_OCCUPIED = "m.location_occupied"; - /** The message identifier for a cluster speak request message. */ - public static final String CLUSTER_SPEAK_REQUEST = "cspkreq"; + /** The message identifier for a cluster speak request. */ + public static final String CLUSTER_SPEAK_REQUEST = "ClusterSpeak"; } diff --git a/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java b/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java index 4aeba856b..1787b5684 100644 --- a/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java +++ b/src/java/com/threerings/whirled/spot/client/SpotSceneDirector.java @@ -1,11 +1,18 @@ // -// $Id: SpotSceneDirector.java,v 1.4 2001/12/16 05:18:20 mdb Exp $ +// $Id: SpotSceneDirector.java,v 1.5 2001/12/16 21:02:18 mdb Exp $ package com.threerings.whirled.spot.client; import java.util.Iterator; import com.samskivert.util.StringUtil; +import com.threerings.presents.dobj.DObject; +import com.threerings.presents.dobj.DObjectManager; +import com.threerings.presents.dobj.ObjectAccessException; +import com.threerings.presents.dobj.Subscriber; + +import com.threerings.crowd.chat.ChatDirector; + import com.threerings.whirled.client.SceneDirector; import com.threerings.whirled.data.SceneModel; import com.threerings.whirled.util.WhirledContext; @@ -19,7 +26,7 @@ import com.threerings.whirled.spot.data.Portal; * locations within a scene. */ public class SpotSceneDirector - implements SpotCodes + implements SpotCodes, Subscriber { /** * This is used to communicate back to the caller of {@link @@ -52,6 +59,15 @@ public class SpotSceneDirector _scdir = scdir; } + /** + * Configures this spot scene director with a chat director, with + * which it will coordinate to implement cluster chatting. + */ + public void setChatDirector (ChatDirector chatdir) + { + _chatdir = chatdir; + } + /** * Requests that this client move to the location specified by the * supplied portal id. A request will be made and when the response is @@ -157,21 +173,64 @@ public class SpotSceneDirector locationId, this); } + /** + * Sends a chat message to the other users in the cluster to which the + * location that we currently occupy belongs. + */ + public void requestClusterSpeak (String message) + { + // make sure we're currently in a scene + DisplaySpotScene scene = (DisplaySpotScene)_scdir.getScene(); + if (scene == null) { + Log.warning("Requested to speak to cluster, but we're not " + + "currently in any scene [message=" + message + "]."); + return; + } + + // make sure we're in a location + if (_locationId > 0) { + SpotService.clusterSpeak( + _ctx.getClient(), scene.getId(), _locationId, message, this); + + } else { + Log.info("Ignoring cluster speak as we're not in a location."); + } + } + /** * Called in response to a successful changeLoc request. */ - public void handleChangeLocSucceeded (int invid) + public void handleChangeLocSucceeded (int invid, int clusterOid) { ChangeObserver obs = _changeObserver; - int locId = _pendingLocId; + _locationId = _pendingLocId; // clear out our pending location info _pendingLocId = -1; _changeObserver = null; + // determine if our cluster oid changed (which we only care about + // if we're doing cluster chat) + if (_chatdir != null) { + int oldOid = (_clobj == null) ? -1 : _clobj.getOid(); + if (clusterOid != oldOid) { + DObjectManager omgr = _ctx.getDObjectManager(); + // remove our old subscription if necessary + if (_clobj != null) { + _chatdir.removeAuxilliarySource(_clobj); + // unsubscribe from our old object + omgr.unsubscribeFromObject(_clobj.getOid(), this); + _clobj = null; + } + // create a new subscription (we'll wire it up to the chat + // director when the subscription completes + omgr.subscribeToObject(clusterOid, this); + } + } + // if we had an observer, let them know things went well if (obs != null) { - obs.locationChangeSucceeded(locId); + obs.locationChangeSucceeded(_locationId); } } @@ -193,16 +252,43 @@ public class SpotSceneDirector } } + // documentation inherited + public void objectAvailable (DObject object) + { + // we've got our cluster chat object, configure the chat director + // with it and keep a reference ourselves + if (_chatdir != null) { + _chatdir.addAuxilliarySource(object); + _clobj = object; + } + } + + // documentation inherited + public void requestFailed (int oid, ObjectAccessException cause) + { + Log.warning("Unable to subscribe to cluster chat object " + + "[oid=" + oid + ",, cause=" + cause + "]."); + } + /** The active client context. */ protected WhirledContext _ctx; /** The scene director with which we are cooperating. */ protected SceneDirector _scdir; + /** A reference to the chat director with which we coordinate. */ + protected ChatDirector _chatdir; + + /** The location id of the location we currently occupy. */ + protected int _locationId = -1; + /** The location id on which we have an outstanding change location * request. */ protected int _pendingLocId = -1; + /** The cluster chat object for the cluster we currently occupy. */ + protected DObject _clobj; + /** An entity that wants to know if a requested location change * succeded or failed. */ protected ChangeObserver _changeObserver; diff --git a/src/java/com/threerings/whirled/spot/client/SpotService.java b/src/java/com/threerings/whirled/spot/client/SpotService.java index 8206c05e2..d6312d6c1 100644 --- a/src/java/com/threerings/whirled/spot/client/SpotService.java +++ b/src/java/com/threerings/whirled/spot/client/SpotService.java @@ -1,5 +1,5 @@ // -// $Id: SpotService.java,v 1.3 2001/12/16 05:18:20 mdb Exp $ +// $Id: SpotService.java,v 1.4 2001/12/16 21:02:18 mdb Exp $ package com.threerings.whirled.spot.client; @@ -48,4 +48,20 @@ public class SpotService implements SpotCodes Log.info("Sent changeLoc request [sceneId=" + sceneId + ", locId=" + locationId + "]."); } + + /** + * Requests that the supplied message be delivered to listeners in the + * cluster to which the specified location belongs. + */ + public static void clusterSpeak ( + Client client, int sceneId, int locationId, String message, + SpotSceneDirector rsptarget) + { + InvocationDirector invdir = client.getInvocationDirector(); + Object[] args = new Object[] { + new Integer(sceneId), new Integer(locationId), message }; + invdir.invoke(MODULE_NAME, CLUSTER_SPEAK_REQUEST, args, rsptarget); + Log.info("Sent clusterSpeak request [sceneId=" + sceneId + + ", locId=" + locationId + ", message=" + message + "]."); + } } diff --git a/src/java/com/threerings/whirled/spot/server/ClusterChatMessageHandler.java b/src/java/com/threerings/whirled/spot/server/ClusterChatMessageHandler.java deleted file mode 100644 index b5fd88440..000000000 --- a/src/java/com/threerings/whirled/spot/server/ClusterChatMessageHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -// -// $Id: ClusterChatMessageHandler.java,v 1.1 2001/12/14 00:12:32 mdb Exp $ - -package com.threerings.whirled.spot.server; - -import com.threerings.presents.dobj.MessageEvent; - -import com.threerings.crowd.data.BodyObject; -import com.threerings.crowd.data.PlaceObject; -import com.threerings.crowd.server.PlaceManager; - -import com.threerings.whirled.server.WhirledServer; -import com.threerings.whirled.spot.Log; - -/** - * The cluster chat message handler handles chat messages that are issued - * to the cluster associated with a particular location, with the - * intention of speaking only to bodies in that cluster. - */ -public class ClusterChatMessageHandler - implements PlaceManager.MessageHandler -{ - /** - * Handles {@link SpotCodes#CLUSTER_SPEAK_REQUEST} messages. - */ - public void handleEvent (MessageEvent event, PlaceManager pmgr) - { - // presently we do no ratification of chat messages, so we just - // generate a chat notification with the message and name of the - // speaker - int soid = event.getSourceOid(); - BodyObject source = (BodyObject)WhirledServer.omgr.getObject(soid); - if (source == null) { - Log.info("Chatter went away. Dropping cluster chat request " + - "[req=" + event + "]."); - return; - } - - // parse our incoming arguments - Object[] inargs = event.getArgs(); - int reqid = ((Integer)inargs[0]).intValue(); - int locid = ((Integer)inargs[1]).intValue(); - String message = (String)inargs[2]; - - // pass this request on to the spot scene manager as it will need - // to check that the location exists and that the requester - // occupies it and so on - ((SpotSceneManager)pmgr).handleClusterChatRequest( - source, locid, message); - } -} diff --git a/src/java/com/threerings/whirled/spot/server/SpotProvider.java b/src/java/com/threerings/whirled/spot/server/SpotProvider.java index a49a8c050..dcdfbb66c 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.4 2001/12/16 05:38:26 mdb Exp $ +// $Id: SpotProvider.java,v 1.5 2001/12/16 21:02:18 mdb Exp $ package com.threerings.whirled.spot.server; @@ -200,8 +200,9 @@ public class SpotProvider extends InvocationProvider throw new ServiceFailedException(INTERNAL_ERROR); } - smgr.handleChangeLocRequest(source, locationId); - sendResponse(source, invid, CHANGE_LOC_SUCCEEDED_RESPONSE); + int locOid = smgr.handleChangeLocRequest(source, locationId); + sendResponse(source, invid, CHANGE_LOC_SUCCEEDED_RESPONSE, + new Integer(locOid)); } catch (ServiceFailedException sfe) { sendResponse(source, invid, CHANGE_LOC_FAILED_RESPONSE, @@ -209,6 +210,29 @@ public class SpotProvider extends InvocationProvider } } + /** + * Handles {@link SpotCodes#CLUSTER_SPEAK_REQUEST} messages. + */ + public void handleClusterSpeakRequest ( + BodyObject source, int invid, int sceneId, int locId, String message) + { + // look up the scene manager for the specified scene + SpotSceneManager smgr = (SpotSceneManager) + _screg.getSceneManager(sceneId); + if (smgr == null) { + Log.warning("User requested cluster chat in " + + "non-existent scene [user=" + source.username + + ", sceneId=" + sceneId + ", locId=" + locId + + ", message=" + message + "]."); + + } else { + // pass this request on to the spot scene manager as it will + // need to check that the location exists and that the + // requester occupies it and so on + smgr.handleClusterSpeakRequest(source, locId, message); + } + } + /** * Looks up the specified place object, obtains the occupant info for * the specified body object and updates the location id in said diff --git a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java index 232d0c6e3..eafd7ce52 100644 --- a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java +++ b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java @@ -1,5 +1,5 @@ // -// $Id: SpotSceneManager.java,v 1.3 2001/12/16 08:07:53 mdb Exp $ +// $Id: SpotSceneManager.java,v 1.4 2001/12/16 21:02:18 mdb Exp $ package com.threerings.whirled.spot.server; @@ -110,11 +110,15 @@ public class SpotSceneManager extends SceneManager * Called by the {@link SpotProvider} when we receive a request by a * user to occupy a particular location. * + * @return the oid of the chat object associated with the cluster to + * which this location belongs or -1 if the location is not part of a + * cluster. + * * @exception ServiceFailedException thrown with a reason code * explaining the location change failure if there is a problem * processing the location change request. */ - protected void handleChangeLocRequest (BodyObject source, int locationId) + protected int handleChangeLocRequest (BodyObject source, int locationId) throws ServiceFailedException { // make sure no one is already in the requested location @@ -154,13 +158,17 @@ public class SpotSceneManager extends SceneManager soi.locationId = locationId; // and broadcast the update to the place _plobj.updateOccupantInfo(soi); + + // figure out the cluster chat oid + int clusterIdx = _sscene.getClusterIndex(locidx); + return (clusterIdx == -1) ? -1 : _clusterOids[clusterIdx]; } /** - * Called by the {@link ClusterChatMessageHandler} when we receive a - * cluster chat request. + * Called by the {@link SpotProvider} when we receive a cluster speak + * request. */ - protected void handleClusterChatRequest ( + protected void handleClusterSpeakRequest ( BodyObject source, int locationId, String message) { // make sure this user occupies the specified location