From e6dc5c38d770f967c231ee04efe7b02903ea07eb Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Sat, 14 Jun 2003 00:47:16 +0000 Subject: [PATCH] The basis for logging all recent chat on the server. Now I have to make every type of chat object known to man capable of reporting who's listening. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2653 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../crowd/chat/data/SpeakObject.java | 25 ++++ .../crowd/chat/server/SpeakProvider.java | 108 +++++++++++++++++- .../crowd/client/LocationDirector.java | 24 ++-- .../threerings/crowd/server/CrowdClient.java | 12 +- 4 files changed, 159 insertions(+), 10 deletions(-) create mode 100644 src/java/com/threerings/crowd/chat/data/SpeakObject.java diff --git a/src/java/com/threerings/crowd/chat/data/SpeakObject.java b/src/java/com/threerings/crowd/chat/data/SpeakObject.java new file mode 100644 index 000000000..10108e309 --- /dev/null +++ b/src/java/com/threerings/crowd/chat/data/SpeakObject.java @@ -0,0 +1,25 @@ +// +// $Id: SpeakObject.java,v 1.1 2003/06/14 00:47:16 mdb Exp $ + +package com.threerings.crowd.chat.data; + +/** + * Provides a mechanism by which the speak service can identify chat + * listeners so as to maintain a recent history of all chat traffic on the + * server. + */ +public interface SpeakObject +{ + /** Used in conjunction with {@link #applyToListeners}. */ + public static interface ListenerOp + { + public void apply (int bodyOid); + } + + /** + * The speak service will call this every time a chat message is + * delivered on this speak object to note the listeners that + * received the message. + */ + public void applyToListeners (ListenerOp op); +} diff --git a/src/java/com/threerings/crowd/chat/server/SpeakProvider.java b/src/java/com/threerings/crowd/chat/server/SpeakProvider.java index 1c6e61fc3..4c64563b0 100644 --- a/src/java/com/threerings/crowd/chat/server/SpeakProvider.java +++ b/src/java/com/threerings/crowd/chat/server/SpeakProvider.java @@ -1,8 +1,11 @@ // -// $Id: SpeakProvider.java,v 1.6 2003/06/04 02:50:18 ray Exp $ +// $Id: SpeakProvider.java,v 1.7 2003/06/14 00:47:16 mdb Exp $ package com.threerings.crowd.chat.server; +import java.util.ArrayList; +import java.util.HashMap; + import com.samskivert.util.ObserverList; import com.threerings.presents.data.ClientObject; @@ -12,9 +15,11 @@ import com.threerings.presents.server.InvocationProvider; import com.threerings.crowd.Log; import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.server.CrowdServer; import com.threerings.crowd.chat.data.ChatCodes; import com.threerings.crowd.chat.data.ChatMessage; +import com.threerings.crowd.chat.data.SpeakObject; import com.threerings.crowd.chat.data.SystemMessage; import com.threerings.crowd.chat.data.UserMessage; @@ -203,6 +208,95 @@ public class SpeakProvider { // post the message to the relevant object speakObj.postMessage(CHAT_NOTIFICATION, new Object[] { msg }); + + // determine to whom this message will be delivered and register + // the message with all parties + if (speakObj instanceof SpeakObject) { + _messageMapper.message = msg; + ((SpeakObject)speakObj).applyToListeners(_messageMapper); + _messageMapper.message = null; + } else { + Log.info("Unable to note listeners [dclass=" + speakObj.getClass() + + ", msg=" + msg + "]."); + } + + // if this is a user message, note the message in their history as + // well + if (msg instanceof UserMessage) { + noteMessage(((UserMessage)msg).speaker, msg); + } + } + + /** + * Returns a list of {@link ChatMessage} objects to which this user + * has been privy in the recent past. + */ + public static ArrayList getChatHistory (String username) + { + ArrayList history = getHistoryList(username); + pruneHistory(System.currentTimeMillis(), history); + return history; + } + + /** + * Called to clear the chat history for the specified user. + */ + public static void clearHistory (String username) + { + Log.info("Clearing history for " + username + "."); + _histories.remove(username); + } + + /** + * Notes that the specified user was privy to the specified + * message. If {@link ChatMessage#timestamp} is not already filled in, + * it will be. + */ + protected static void noteMessage (String username, ChatMessage msg) + { + if (msg.timestamp == 0L) { + msg.timestamp = System.currentTimeMillis(); + } + getHistoryList(username).add(msg); + } + + /** + * Returns this user's chat history, creating one if necessary. + */ + protected static ArrayList getHistoryList (String username) + { + ArrayList history = (ArrayList)_histories.get(username); + if (history == null) { + _histories.put(username, history = new ArrayList()); + } + return history; + } + + /** + * Prunes all messages from this history which are expired. + */ + protected static void pruneHistory (long now, ArrayList history) + { + for (int ii = history.size()-1; ii >= 0; ii++) { + ChatMessage msg = (ChatMessage)history.get(ii); + if (now - msg.timestamp > HISTORY_EXPIRATION) { + Log.info("Expiring from history " + msg + "."); + history.remove(ii); + } + } + } + + /** Used to note the recipients of a chat message. */ + protected static class MessageMapper implements SpeakObject.ListenerOp + { + public ChatMessage message; + + public void apply (int bodyOid) { + DObject dobj = CrowdServer.omgr.getObject(bodyOid); + if (dobj != null && dobj instanceof BodyObject) { + noteMessage(((BodyObject)dobj).username, message); + } + } } /** Our speech object. */ @@ -210,4 +304,16 @@ public class SpeakProvider /** The entity that will validate our speakers. */ protected SpeakerValidator _validator; + + /** Recent chat history for the server. */ + protected static HashMap _histories = new HashMap(); + + /** Maintains a mapping of listener identifiers. */ + protected static HashMap _identers = new HashMap(); + + /** Used to note the recipients of a chat message. */ + protected static MessageMapper _messageMapper = new MessageMapper(); + + /** The amount of time before chat history becomes... history. */ + protected static final long HISTORY_EXPIRATION = 5L * 60L * 1000L; } diff --git a/src/java/com/threerings/crowd/client/LocationDirector.java b/src/java/com/threerings/crowd/client/LocationDirector.java index 94282f12f..ef10f2d08 100644 --- a/src/java/com/threerings/crowd/client/LocationDirector.java +++ b/src/java/com/threerings/crowd/client/LocationDirector.java @@ -1,5 +1,5 @@ // -// $Id: LocationDirector.java,v 1.29 2003/01/09 02:46:58 mdb Exp $ +// $Id: LocationDirector.java,v 1.30 2003/06/14 00:47:16 mdb Exp $ package com.threerings.crowd.client; @@ -93,6 +93,14 @@ public class LocationDirector extends BasicDirector return _plobj; } + /** + * Returns true if there is a pending move request. + */ + public boolean movePending () + { + return (_pendingPlaceId > 0); + } + /** * Requests that this client be moved to the specified place. A * request will be made and when the response is received, the @@ -415,16 +423,18 @@ public class LocationDirector extends BasicDirector } // documentation inherited from interface - public void forcedMove (int placeId) + public void forcedMove (final int placeId) { Log.info("Moving at request of server [placeId=" + placeId + "]."); - // clear out our old place information - mayLeavePlace(); - didLeavePlace(); + if (movePending()) { + // clear out our old place information + mayLeavePlace(); + didLeavePlace(); - // move to the new place - moveTo(placeId); + // move to the new place + moveTo(placeId); + } } /** diff --git a/src/java/com/threerings/crowd/server/CrowdClient.java b/src/java/com/threerings/crowd/server/CrowdClient.java index 4623739bd..035721c58 100644 --- a/src/java/com/threerings/crowd/server/CrowdClient.java +++ b/src/java/com/threerings/crowd/server/CrowdClient.java @@ -1,5 +1,5 @@ // -// $Id: CrowdClient.java,v 1.22 2002/12/09 17:19:04 mdb Exp $ +// $Id: CrowdClient.java,v 1.23 2003/06/14 00:47:16 mdb Exp $ package com.threerings.crowd.server; @@ -7,6 +7,7 @@ import com.threerings.presents.data.ClientObject; import com.threerings.presents.server.PresentsClient; import com.threerings.crowd.Log; +import com.threerings.crowd.chat.server.SpeakProvider; import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.OccupantInfo; import com.threerings.crowd.data.PlaceObject; @@ -53,9 +54,16 @@ public class CrowdClient extends PresentsClient { super.sessionDidEnd(); + BodyObject body = (BodyObject)_clobj; + // clear out our location so that anyone listening for such things // will know that we've left - clearLocation((BodyObject)_clobj); + clearLocation(body); + + // clear our chat history + if (body != null) { + SpeakProvider.clearHistory(body.username); + } } /**