From a7c7d853fe27206fe5db34195ea2afd6954220e5 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Sun, 8 Jun 2008 13:06:03 +0000 Subject: [PATCH] Handle the BodyService with a BodyManager instead of a concrete BodyProvider. More dependency injection (or removal in the case of SpeakUtil). git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5163 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- build.xml | 1 - .../crowd/chat/server/SpeakUtil.java | 34 ++--- .../crowd/peer/server/CrowdPeerManager.java | 18 +-- .../threerings/crowd/server/BodyManager.java | 123 ++++++++++++++++++ .../threerings/crowd/server/BodyProvider.java | 101 +------------- .../threerings/crowd/server/CrowdClient.java | 6 +- .../threerings/crowd/server/CrowdServer.java | 10 +- 7 files changed, 167 insertions(+), 126 deletions(-) create mode 100644 src/java/com/threerings/crowd/server/BodyManager.java diff --git a/build.xml b/build.xml index a74e4ff6e..a54bfd4af 100644 --- a/build.xml +++ b/build.xml @@ -72,7 +72,6 @@ - diff --git a/src/java/com/threerings/crowd/chat/server/SpeakUtil.java b/src/java/com/threerings/crowd/chat/server/SpeakUtil.java index 0dba95774..65df555a5 100644 --- a/src/java/com/threerings/crowd/chat/server/SpeakUtil.java +++ b/src/java/com/threerings/crowd/chat/server/SpeakUtil.java @@ -21,18 +21,21 @@ package com.threerings.crowd.chat.server; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.samskivert.util.ObserverList; import com.threerings.util.Name; import com.threerings.presents.data.ClientObject; import com.threerings.presents.dobj.DObject; +import com.threerings.presents.dobj.RootDObjectManager; import com.threerings.presents.server.InvocationProvider; import com.threerings.crowd.data.BodyObject; -import com.threerings.crowd.server.CrowdServer; import com.threerings.crowd.chat.client.SpeakService; import com.threerings.crowd.chat.data.ChatCodes; @@ -188,8 +191,10 @@ public class SpeakUtil return; } else if (speakObj instanceof SpeakObject) { + _messageMapper.omgr = (RootDObjectManager)speakObj.getManager(); _messageMapper.message = (UserMessage)msg; ((SpeakObject)speakObj).applyToListeners(_messageMapper); + _messageMapper.omgr = null; _messageMapper.message = null; } else { @@ -202,9 +207,9 @@ public class SpeakUtil * Returns a list of {@link ChatMessage} objects to which this user has been privy in the * recent past. */ - public static ArrayList getChatHistory (Name username) + public static List getChatHistory (Name username) { - ArrayList history = getHistoryList(username); + List history = getHistoryList(username); pruneHistory(System.currentTimeMillis(), history); return history; } @@ -231,7 +236,7 @@ public class SpeakUtil for (Name username : usernames) { // add the message to this user's chat history - ArrayList history = getHistoryList(username); + List history = getHistoryList(username); history.add(msg); // if the history is big enough, potentially prune it (we always prune when asked for @@ -272,11 +277,11 @@ public class SpeakUtil /** * Returns this user's chat history, creating one if necessary. */ - protected static ArrayList getHistoryList (Name username) + protected static List getHistoryList (Name username) { - ArrayList history = _histories.get(username); + List history = _histories.get(username); if (history == null) { - _histories.put(username, history = new ArrayList()); + _histories.put(username, history = Lists.newArrayList()); } return history; } @@ -284,7 +289,7 @@ public class SpeakUtil /** * Prunes all messages from this history which are expired. */ - protected static void pruneHistory (long now, ArrayList history) + protected static void pruneHistory (long now, List history) { int prunepos = 0; for (int ll = history.size(); prunepos < ll; prunepos++) { @@ -299,10 +304,11 @@ public class SpeakUtil /** Used to note the recipients of a chat message. */ protected static class MessageMapper implements SpeakObject.ListenerOp { + public RootDObjectManager omgr; public UserMessage message; public void apply (int bodyOid) { - DObject dobj = CrowdServer.omgr.getObject(bodyOid); + DObject dobj = omgr.getObject(bodyOid); if (dobj != null && dobj instanceof BodyObject) { noteMessage(((BodyObject)dobj).getVisibleName(), message); } @@ -332,15 +338,13 @@ public class SpeakUtil } /** Recent chat history for the server. */ - protected static HashMap> _histories = - new HashMap>(); + protected static Map> _histories = Maps.newHashMap(); /** Used to note the recipients of a chat message. */ protected static MessageMapper _messageMapper = new MessageMapper(); /** A list of {@link MessageObserver}s. */ - protected static ObserverList _messageObs = - new ObserverList(ObserverList.FAST_UNSAFE_NOTIFY); + protected static ObserverList _messageObs = ObserverList.newFastUnsafe(); /** Used to notify our {@link MessageObserver}s. */ protected static MessageObserverOp _messageOp = new MessageObserverOp(); diff --git a/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java b/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java index 94ac83b02..1af71e647 100644 --- a/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java +++ b/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java @@ -28,6 +28,7 @@ import com.threerings.util.Name; import com.threerings.presents.data.ClientObject; import com.threerings.presents.server.InvocationException; +import com.threerings.presents.server.InvocationManager; import com.threerings.presents.server.PresentsClient; import com.threerings.presents.server.ShutdownManager; @@ -41,7 +42,6 @@ import com.threerings.crowd.chat.data.ChatMessage; import com.threerings.crowd.chat.data.UserMessage; import com.threerings.crowd.chat.server.ChatProvider; import com.threerings.crowd.data.BodyObject; -import com.threerings.crowd.server.CrowdServer; import com.threerings.crowd.peer.data.CrowdClientInfo; import com.threerings.crowd.peer.data.CrowdNodeObject; @@ -68,7 +68,7 @@ public class CrowdPeerManager extends PeerManager throws InvocationException { // we just forward the message as if it originated on this server - CrowdServer.chatprov.deliverTell(message, target, listener); + _chatprov.deliverTell(message, target, listener); } // from interface CrowdPeerProvider @@ -76,7 +76,7 @@ public class CrowdPeerManager extends PeerManager boolean attention) { // deliver the broadcast locally on this server - CrowdServer.chatprov.broadcast(from, bundle, msg, attention, false); + _chatprov.broadcast(from, bundle, msg, attention, false); } // from interface ChatProvider.ChatForwarder @@ -116,11 +116,11 @@ public class CrowdPeerManager extends PeerManager // unregister our invocation service if (_nodeobj != null) { - CrowdServer.invmgr.clearDispatcher(((CrowdNodeObject)_nodeobj).crowdPeerService); + _invmgr.clearDispatcher(((CrowdNodeObject)_nodeobj).crowdPeerService); } // clear our chat forwarder registration - CrowdServer.chatprov.setChatForwarder(null); + _chatprov.setChatForwarder(null); } @Override // documentation inherited @@ -151,10 +151,12 @@ public class CrowdPeerManager extends PeerManager // register and initialize our invocation service CrowdNodeObject cnobj = (CrowdNodeObject)_nodeobj; cnobj.setCrowdPeerService( - (CrowdPeerMarshaller)CrowdServer.invmgr.registerDispatcher( - new CrowdPeerDispatcher(this))); + (CrowdPeerMarshaller)_invmgr.registerDispatcher(new CrowdPeerDispatcher(this))); // register ourselves as a chat forwarder - CrowdServer.chatprov.setChatForwarder(this); + _chatprov.setChatForwarder(this); } + + @Inject protected InvocationManager _invmgr; + @Inject protected ChatProvider _chatprov; } diff --git a/src/java/com/threerings/crowd/server/BodyManager.java b/src/java/com/threerings/crowd/server/BodyManager.java new file mode 100644 index 000000000..bd5672280 --- /dev/null +++ b/src/java/com/threerings/crowd/server/BodyManager.java @@ -0,0 +1,123 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2008 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// 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.crowd.server; + +import com.google.inject.Inject; + +import com.threerings.presents.data.ClientObject; +import com.threerings.presents.server.InvocationException; +import com.threerings.presents.server.InvocationManager; +import com.threerings.presents.server.InvocationProvider; + +import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.CrowdCodes; +import com.threerings.crowd.data.OccupantInfo; +import com.threerings.crowd.data.Place; + +import static com.threerings.crowd.Log.log; + +/** + * Handles body related services. + */ +public class BodyManager + implements BodyProvider +{ + /** Used by {@link #updateOccupantInfo}. */ + public static interface OccupantInfoOp + { + /** + * Updates the supplied occupant info record. + * + * @return true if changes were made and thus the object should be published anew to the + * place object, false if no publish should be done. + */ + public boolean update (OccupantInfo oinfo); + } + + /** + * Constructs and initializes the body manager. + */ + @Inject public BodyManager (InvocationManager invmgr) + { + invmgr.registerDispatcher(new BodyDispatcher(this), CrowdCodes.CROWD_GROUP); + } + + /** + * Locates the specified body's occupant info in the specified location, applies the supplied + * occuapnt info operation to it and then broadcasts the updated info (assuming the occop + * returned true indicating that an update was made). + */ + public void updateOccupantInfo (BodyObject body, Place location, OccupantInfoOp occop) + { + PlaceManager pmgr = (location == null) ? null : + CrowdServer.plreg.getPlaceManager(location.placeOid); + if (pmgr == null) { + return; + } + + OccupantInfo info = pmgr.getOccupantInfo(body.getOid()); + if (info != null && occop.update(info)) { + pmgr.updateOccupantInfo(info); + } + } + + /** + * Updates the connection status for the given body object's occupant info in the specified + * location. + */ + public void updateOccupantStatus (BodyObject body, Place location, final byte status) + { + // no need to NOOP + if (body.status != status) { + // update the status in their body object + body.setStatus(status); + body.statusTime = System.currentTimeMillis(); + } + + updateOccupantInfo(body, location, new OccupantInfoOp() { + public boolean update (OccupantInfo info) { + if (info.status != status) { + info.status = status; + return true; + } else { + return false; + } + } + }); + } + + // from interface BodyProvider + public void setIdle (ClientObject caller, boolean idle) + { + BodyObject bobj = (BodyObject)caller; + + // determine the body's proposed new status + byte nstatus = (idle) ? OccupantInfo.IDLE : OccupantInfo.ACTIVE; + if (bobj.status == nstatus) { + return; // ignore NOOP attempts + } + + // update their status! + log.debug("Setting user idle state [user=" + bobj.username + ", status=" + nstatus + "]."); + updateOccupantStatus(bobj, bobj.location, nstatus); + } +} diff --git a/src/java/com/threerings/crowd/server/BodyProvider.java b/src/java/com/threerings/crowd/server/BodyProvider.java index 98dea9a52..4c40b9dd1 100644 --- a/src/java/com/threerings/crowd/server/BodyProvider.java +++ b/src/java/com/threerings/crowd/server/BodyProvider.java @@ -2,7 +2,7 @@ // $Id$ // // Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// Copyright (C) 2002-2008 Three Rings Design, Inc., All Rights Reserved // http://www.threerings.net/code/narya/ // // This library is free software; you can redistribute it and/or modify it @@ -22,106 +22,15 @@ package com.threerings.crowd.server; import com.threerings.presents.data.ClientObject; -import com.threerings.presents.server.InvocationException; -import com.threerings.presents.server.InvocationManager; import com.threerings.presents.server.InvocationProvider; -import com.threerings.crowd.data.BodyObject; -import com.threerings.crowd.data.CrowdCodes; -import com.threerings.crowd.data.OccupantInfo; -import com.threerings.crowd.data.Place; - -import static com.threerings.crowd.Log.log; - /** - * Provides the server-side side of the body-related invocation services. + * Defines the server-side of the {@link BodyService}. */ -public class BodyProvider - implements InvocationProvider +public interface BodyProvider extends InvocationProvider { - /** Used by {@link #updateOccupantInfo}. */ - public static interface OccupantInfoOp - { - /** - * Updates the supplied occupant info record, returning true if - * changes were made and thus the object should be published anew - * to the place object, false if no publish should be done. - */ - public boolean update (OccupantInfo oinfo); - } - /** - * Constructs and initializes a body provider instance which will be - * used to handle all body-related invocation service requests. + * Handles a {@link BodyService#setIdle} request. */ - public static void init (InvocationManager invmgr) - { - // register a provider instance - invmgr.registerDispatcher(new BodyDispatcher(new BodyProvider()), CrowdCodes.CROWD_GROUP); - } - - /** - * Handles a request to set the idle state of a client to the specified value. - */ - public void setIdle (ClientObject caller, boolean idle) - throws InvocationException - { - BodyObject bobj = (BodyObject)caller; - - // determine the body's proposed new status - byte nstatus = (idle) ? OccupantInfo.IDLE : OccupantInfo.ACTIVE; - - // report NOOP attempts - if (bobj.status == nstatus) { - throw new InvocationException((idle) ? "m.already_idle" : "m.already_active"); - } - - // update their status! - log.debug("Setting user idle state [user=" + bobj.username + ", status=" + nstatus + "]."); - updateOccupantStatus(bobj, bobj.location, nstatus); - } - - /** - * Locates the specified body's occupant info in the specified location, applies the supplied - * occuapnt info operation to it and then broadcasts the updated info (assuming the occop - * returned true indicating that an update was made). - */ - public static void updateOccupantInfo (BodyObject body, Place location, OccupantInfoOp occop) - { - PlaceManager pmgr = (location == null) ? null : - CrowdServer.plreg.getPlaceManager(location.placeOid); - if (pmgr == null) { - return; - } - - OccupantInfo info = pmgr.getOccupantInfo(body.getOid()); - if (info != null && occop.update(info)) { - pmgr.updateOccupantInfo(info); - } - } - - /** - * Updates the connection status for the given body object's occupant info in the specified - * location. - */ - public static void updateOccupantStatus (BodyObject body, Place location, final byte status) - { - // no need to NOOP - if (body.status != status) { - // update the status in their body object - body.setStatus(status); - body.statusTime = System.currentTimeMillis(); - } - - updateOccupantInfo(body, location, new OccupantInfoOp() { - public boolean update (OccupantInfo info) { - if (info.status != status) { - info.status = status; - return true; - } else { - return false; - } - } - }); - } + public void setIdle (ClientObject caller, boolean arg1); } diff --git a/src/java/com/threerings/crowd/server/CrowdClient.java b/src/java/com/threerings/crowd/server/CrowdClient.java index 62689ccef..6785d2011 100644 --- a/src/java/com/threerings/crowd/server/CrowdClient.java +++ b/src/java/com/threerings/crowd/server/CrowdClient.java @@ -42,7 +42,7 @@ public class CrowdClient extends PresentsClient if (_clobj != null) { // note that the user is disconnected BodyObject bobj = (BodyObject)_clobj; - BodyProvider.updateOccupantStatus(bobj, bobj.location, OccupantInfo.DISCONNECTED); + CrowdServer.bodyman.updateOccupantStatus(bobj, bobj.location, OccupantInfo.DISCONNECTED); } } @@ -53,7 +53,7 @@ public class CrowdClient extends PresentsClient // note that the user's active once more BodyObject bobj = (BodyObject)_clobj; - BodyProvider.updateOccupantStatus(bobj, bobj.location, OccupantInfo.ACTIVE); + CrowdServer.bodyman.updateOccupantStatus(bobj, bobj.location, OccupantInfo.ACTIVE); } // documentation inherited @@ -68,7 +68,7 @@ public class CrowdClient extends PresentsClient // reset our status in case this object remains around until they start their next session // (which could happen very soon) - BodyProvider.updateOccupantStatus(body, null, OccupantInfo.ACTIVE); + CrowdServer.bodyman.updateOccupantStatus(body, null, OccupantInfo.ACTIVE); // clear our chat history if (body != null) { diff --git a/src/java/com/threerings/crowd/server/CrowdServer.java b/src/java/com/threerings/crowd/server/CrowdServer.java index 1984b4ac3..584422075 100644 --- a/src/java/com/threerings/crowd/server/CrowdServer.java +++ b/src/java/com/threerings/crowd/server/CrowdServer.java @@ -64,6 +64,9 @@ public class CrowdServer extends PresentsServer /** Our chat provider. */ public static ChatProvider chatprov; + /** Our body manager. */ + public static BodyManager bodyman; + /** * Initializes all of the server services and prepares for operation. */ @@ -75,6 +78,7 @@ public class CrowdServer extends PresentsServer // LEGACY: set up our legacy static references plreg = _plreg; chatprov = _chatprov; + bodyman = _bodyman; // configure the client manager to use our bits clmgr.setClientFactory(new ClientFactory() { @@ -88,9 +92,6 @@ public class CrowdServer extends PresentsServer // create our body locator _lookup = createBodyLocator(); - - // initialize the body services - BodyProvider.init(invmgr); } /** @@ -151,6 +152,9 @@ public class CrowdServer extends PresentsServer /** Handles the creation and tracking of place managers. */ @Inject protected PlaceRegistry _plreg; + /** Handles body-related invocation services. */ + @Inject protected BodyManager _bodyman; + /** Provides chat-related invocation services. */ @Inject protected ChatProvider _chatprov;