If we're going to do this, I guess we're going to do it properly. Nixed the
notion of a global group (though we implicitly define one in InvocationCodes) added a mechanism for directors (which generally handle the client side of invocation services) to register their interest in bootstrap service groups so that the whole goddamned complex business can happen magically behind the scenes. If you instantiate a director, it will automatically register interest in the service group it needs and everything will work. If you don't use the director code, you don't get the services and you can safely exclude all of that code from your client even though the services are still in use on the server (and presumably used by some other types of clients). This is going to break all the builds, which I'll soon fix. Then I'll go write all this in ActionScript. Yay! git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4552 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,54 +1,56 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
package com.threerings.admin.client;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.admin.Log;
|
||||
import com.threerings.admin.data.ConfigObject;
|
||||
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.SessionObserver;
|
||||
import com.threerings.presents.client.ClientAdapter;
|
||||
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.admin.Log;
|
||||
import com.threerings.admin.data.AdminCodes;
|
||||
import com.threerings.admin.data.ConfigObject;
|
||||
|
||||
/**
|
||||
* Handles subscribing to admin config objects.
|
||||
*/
|
||||
public class ConfigObjectManager implements AdminService.ConfigInfoListener
|
||||
{
|
||||
public ConfigObjectManager(Client client) {
|
||||
public ConfigObjectManager(Client client)
|
||||
{
|
||||
_serverconfig = new HashMap<String,ConfigObject>();
|
||||
_client = client;
|
||||
_client.addClientObserver(new SessionObserver() {
|
||||
// documentation inherited from interface SessionObserver
|
||||
_client.addClientObserver(new ClientAdapter() {
|
||||
public void clientWillLogon (Client client) {
|
||||
client.addServiceGroup(AdminCodes.ADMIN_GROUP);
|
||||
}
|
||||
public void clientDidLogon (Client client) {
|
||||
// Initialize the dobjmgr
|
||||
_dobjmgr = _client.getDObjectManager();
|
||||
// Now that we're logged on, let's grab the server configs
|
||||
_service = (AdminService)
|
||||
client.requireService(AdminService.class);
|
||||
_service = (AdminService)client.requireService(AdminService.class);
|
||||
getConfigInfo();
|
||||
}
|
||||
|
||||
// documentation inherited from interface SessionObserver
|
||||
public void clientDidLogoff (Client client) {
|
||||
// Clean up our subscription to the server's configuration
|
||||
for (int ii = 0; ii < _csubscribers.length; ii++) {
|
||||
_csubscribers[ii].cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface SessionObserver
|
||||
public void clientObjectDidChange (Client client) {}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience: generate a getConfigInfo request to the AdminService
|
||||
* from the external class, instead from within the anonymous inner class
|
||||
* Returns the ConfigObject identified by the given key
|
||||
*/
|
||||
protected void getConfigInfo() {
|
||||
_service.getConfigInfo(_client, this);
|
||||
public ConfigObject getServerConfig (String key)
|
||||
{
|
||||
return _serverconfig.get(key);
|
||||
}
|
||||
|
||||
// documentation inherited from interface AdminService.ConfigInfoListener
|
||||
@@ -60,29 +62,32 @@ public class ConfigObjectManager implements AdminService.ConfigInfoListener
|
||||
_csubscribers[ii].subscribeConfig(keys[ii], oids[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// documentation inherited from interface AdminService.ConfigInfoListener
|
||||
public void requestFailed (String reason) {
|
||||
public void requestFailed (String reason)
|
||||
{
|
||||
Log.warning("Oh bugger, we didn't get the config data: " + reason);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ConfigObject identified by the given key
|
||||
* Convenience: generate a getConfigInfo request to the AdminService from the external class,
|
||||
* instead from within the anonymous inner class
|
||||
*/
|
||||
public ConfigObject getServerConfig (String key) {
|
||||
return _serverconfig.get(key);
|
||||
protected void getConfigInfo()
|
||||
{
|
||||
_service.getConfigInfo(_client, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class takes care of the details of subscribing to and placing
|
||||
* an individual ConfigObject that the server knows about into a HashMap
|
||||
* This class takes care of the details of subscribing to and placing an individual
|
||||
* ConfigObject that the server knows about into a HashMap
|
||||
*/
|
||||
protected class ConfigObjectSubscriber implements Subscriber<ConfigObject>
|
||||
{
|
||||
/**
|
||||
* This method requests that we place a subscription to the
|
||||
* ConfigObject with the given oid, identified by the key; when the
|
||||
* object becomes available, it's added to our serverconfig map.
|
||||
* This method requests that we place a subscription to the ConfigObject with the given
|
||||
* oid, identified by the key; when the object becomes available, it's added to our
|
||||
* serverconfig map.
|
||||
*/
|
||||
public void subscribeConfig (String key, int oid) {
|
||||
_key = key;
|
||||
@@ -95,15 +100,15 @@ public class ConfigObjectManager implements AdminService.ConfigInfoListener
|
||||
_cobj = object;
|
||||
_serverconfig.put(_key, _cobj);
|
||||
}
|
||||
|
||||
|
||||
// documentation inherited from interface Subscriber
|
||||
public void requestFailed (int oid, ObjectAccessException cause) {
|
||||
Log.warning("Unable to subscribe to config object " + _key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signals that we should stop subscribing to our ConfigObject,
|
||||
* and flush out the entry from the serverconfig map.
|
||||
* Signals that we should stop subscribing to our ConfigObject, and flush out the entry
|
||||
* from the serverconfig map.
|
||||
*/
|
||||
public void cleanup () {
|
||||
// clear out our subscription
|
||||
@@ -114,26 +119,26 @@ public class ConfigObjectManager implements AdminService.ConfigInfoListener
|
||||
|
||||
/** The object that we are tracking */
|
||||
protected ConfigObject _cobj;
|
||||
|
||||
|
||||
/** The name of the config object that we are subscribing to */
|
||||
protected String _key;
|
||||
|
||||
|
||||
/** The oid of the object that we're tracking */
|
||||
protected int _oid;
|
||||
}
|
||||
|
||||
|
||||
/** An array of handlers that each subscribe to a single ConfigObject */
|
||||
protected ConfigObjectSubscriber[] _csubscribers;
|
||||
|
||||
|
||||
/** Our local copy of the server-side runtime configuration */
|
||||
protected HashMap<String,ConfigObject> _serverconfig;
|
||||
|
||||
|
||||
/** Our distributed object manager */
|
||||
protected DObjectManager _dobjmgr;
|
||||
|
||||
|
||||
/** Our admin service that we're using to fetch data */
|
||||
protected AdminService _service;
|
||||
|
||||
|
||||
/** Our client object */
|
||||
protected Client _client;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 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.admin.data;
|
||||
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
|
||||
/**
|
||||
* Codes and consants relating to the admin services.
|
||||
*/
|
||||
public interface AdminCodes extends InvocationCodes
|
||||
{
|
||||
/** Defines our invocation service group. */
|
||||
public static final String ADMIN_GROUP = "presents.admin";
|
||||
}
|
||||
@@ -26,36 +26,32 @@ import com.threerings.presents.server.InvocationManager;
|
||||
import com.threerings.presents.server.InvocationProvider;
|
||||
|
||||
import com.threerings.admin.client.AdminService;
|
||||
import com.threerings.admin.data.AdminCodes;
|
||||
|
||||
/**
|
||||
* Provides the server-side implementation of various administrator
|
||||
* services.
|
||||
* Provides the server-side implementation of various administrator services.
|
||||
*/
|
||||
public class AdminProvider implements InvocationProvider
|
||||
{
|
||||
/**
|
||||
* Constructs an admin provider and registers it with the invocation
|
||||
* manager to handle admin services. This must be called by any server
|
||||
* that wishes to make use of the admin services.
|
||||
* Constructs an admin provider and registers it with the invocation manager to handle admin
|
||||
* services. This must be called by any server that wishes to make use of the admin services.
|
||||
*/
|
||||
public static void init (InvocationManager invmgr, ConfigRegistry registry)
|
||||
{
|
||||
invmgr.registerDispatcher(
|
||||
new AdminDispatcher(new AdminProvider(registry)), true);
|
||||
new AdminDispatcher(new AdminProvider(registry)), AdminCodes.ADMIN_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request for the list of config objects.
|
||||
*/
|
||||
public void getConfigInfo (
|
||||
ClientObject caller, AdminService.ConfigInfoListener listener)
|
||||
public void getConfigInfo (ClientObject caller, AdminService.ConfigInfoListener listener)
|
||||
{
|
||||
// we don't have to validate the request because the user can't do
|
||||
// anything with the keys or oids unless they're an admin (we put the
|
||||
// burden of doing that checking on the creator of the config object
|
||||
// because we would otherwise need some mechanism to determine whether
|
||||
// a user is an admin and we don't want to force some primitive system
|
||||
// on the service user)
|
||||
// we don't have to validate the request because the user can't do anything with the keys
|
||||
// or oids unless they're an admin (we put the burden of doing that checking on the creator
|
||||
// of the config object because we would otherwise need some mechanism to determine whether
|
||||
// a user is an admin and we don't want to force some primitive system on the service user)
|
||||
String[] keys = _registry.getKeys();
|
||||
int[] oids = new int[keys.length];
|
||||
for (int ii = 0; ii < keys.length; ii++) {
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.threerings.util.TimeUtil;
|
||||
import com.threerings.crowd.Log;
|
||||
import com.threerings.crowd.client.LocationObserver;
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.CrowdCodes;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
@@ -1002,7 +1003,13 @@ public class ChatDirector extends BasicDirector
|
||||
return (type == null) ? PLACE_CHAT_TYPE : type;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
@Override // from BasicDirector
|
||||
protected void registerServices (Client client)
|
||||
{
|
||||
client.addServiceGroup(CrowdCodes.CROWD_GROUP);
|
||||
}
|
||||
|
||||
@Override // from BasicDirector
|
||||
protected void fetchServices (Client client)
|
||||
{
|
||||
// get a handle on our chat service
|
||||
|
||||
@@ -33,19 +33,19 @@ import com.threerings.crowd.chat.client.SpeakService;
|
||||
*/
|
||||
public interface ChatCodes extends InvocationCodes
|
||||
{
|
||||
/** A return value used by the ChatDirector and possibly other entities
|
||||
* to indicate successful processing of chat. */
|
||||
/** A return value used by the ChatDirector and possibly other entities to indicate successful
|
||||
* processing of chat. */
|
||||
public static final String SUCCESS = "success";
|
||||
|
||||
/** The message identifier for a chat notification message. */
|
||||
public static final String CHAT_NOTIFICATION = "chat";
|
||||
|
||||
/** The access control identifier for normal chat privileges. See
|
||||
* {@link BodyObject#checkAccess}. */
|
||||
/** The access control identifier for normal chat privileges. See {@link
|
||||
* BodyObject#checkAccess}. */
|
||||
public static final String CHAT_ACCESS = "crowd.chat.chat";
|
||||
|
||||
/** The access control identifier for broadcast chat privileges. See
|
||||
* {@link BodyObject#checkAccess}. */
|
||||
/** The access control identifier for broadcast chat privileges. See {@link
|
||||
* BodyObject#checkAccess}. */
|
||||
public static final String BROADCAST_ACCESS = "crowd.chat.broadcast";
|
||||
|
||||
/** The configuration key for idle time. */
|
||||
@@ -54,10 +54,9 @@ public interface ChatCodes extends InvocationCodes
|
||||
/** The default time after which a player is assumed idle. */
|
||||
public static final long DEFAULT_IDLE_TIME = 3 * 60 * 1000L;
|
||||
|
||||
/** The chat localtype code for chat messages delivered on the place
|
||||
* object currently occupied by the client. This is the only type of
|
||||
* chat message that will be delivered unless the chat director is
|
||||
* explicitly provided with other chat message sources via {@link
|
||||
/** The chat localtype code for chat messages delivered on the place object currently occupied
|
||||
* by the client. This is the only type of chat message that will be delivered unless the chat
|
||||
* director is explicitly provided with other chat message sources via {@link
|
||||
* ChatDirector#addAuxiliarySource}. */
|
||||
public static final String PLACE_CHAT_TYPE = "placeChat";
|
||||
|
||||
@@ -67,21 +66,18 @@ public interface ChatCodes extends InvocationCodes
|
||||
/** The default mode used by {@link SpeakService#speak} requests. */
|
||||
public static final byte DEFAULT_MODE = 0;
|
||||
|
||||
/** A {@link SpeakService#speak} mode to indicate that the user is
|
||||
* thinking what they're saying, or is it that they're saying what
|
||||
* they're thinking? */
|
||||
/** A {@link SpeakService#speak} mode to indicate that the user is thinking what they're
|
||||
* saying, or is it that they're saying what they're thinking? */
|
||||
public static final byte THINK_MODE = 1;
|
||||
|
||||
/** A {@link SpeakService#speak} mode to indicate that a speak is
|
||||
* actually an emote. */
|
||||
/** A {@link SpeakService#speak} mode to indicate that a speak is actually an emote. */
|
||||
public static final byte EMOTE_MODE = 2;
|
||||
|
||||
/** A {@link SpeakService#speak} mode to indicate that a speak is
|
||||
* actually a shout. */
|
||||
/** A {@link SpeakService#speak} mode to indicate that a speak is actually a shout. */
|
||||
public static final byte SHOUT_MODE = 3;
|
||||
|
||||
/** A {@link SpeakService#speak} mode to indicate that a speak is
|
||||
* actually a server-wide broadcast. */
|
||||
/** A {@link SpeakService#speak} mode to indicate that a speak is actually a server-wide
|
||||
* broadcast. */
|
||||
public static final byte BROADCAST_MODE = 4;
|
||||
|
||||
/** String translations for the various chat modes. */
|
||||
@@ -89,11 +85,9 @@ public interface ChatCodes extends InvocationCodes
|
||||
"default", "think", "emote", "shout", "broadcast"
|
||||
};
|
||||
|
||||
/** An error code delivered when the user targeted for a tell
|
||||
* notification is not online. */
|
||||
/** An error code delivered when the user targeted for a tell notification is not online. */
|
||||
public static final String USER_NOT_ONLINE = "m.user_not_online";
|
||||
|
||||
/** An error code delivered when the user targeted for a tell
|
||||
* notification is disconnected. */
|
||||
/** An error code delivered when the user targeted for a tell notification is disconnected. */
|
||||
public static final String USER_DISCONNECTED = "m.user_disconnected";
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ 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.PlaceObject;
|
||||
import com.threerings.crowd.server.CrowdServer;
|
||||
@@ -58,32 +59,29 @@ public class ChatProvider
|
||||
public static interface TellAutoResponder
|
||||
{
|
||||
/**
|
||||
* Called following the delivery of <code>message</code> from
|
||||
* <code>teller</code> to <code>tellee</code>.
|
||||
* Called following the delivery of <code>message</code> from <code>teller</code> to
|
||||
* <code>tellee</code>.
|
||||
*/
|
||||
public void sentTell (BodyObject teller, BodyObject tellee,
|
||||
String message);
|
||||
public void sentTell (BodyObject teller, BodyObject tellee, String message);
|
||||
}
|
||||
|
||||
/** Used to forward tells between servers in a multi-server setup. */
|
||||
public static interface TellForwarder
|
||||
{
|
||||
/**
|
||||
* Requests that the supplied tell message be delivered to the
|
||||
* appropriate destination.
|
||||
* Requests that the supplied tell message be delivered to the appropriate destination.
|
||||
*
|
||||
* @return true if the tell was delivered, false otherwise.
|
||||
*/
|
||||
public boolean forwardTell (UserMessage message, Name target,
|
||||
TellListener listener);
|
||||
public boolean forwardTell (UserMessage message, Name target, TellListener listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an object to which all broadcasts should be sent, rather
|
||||
* than iterating over the place objects and sending to each of them.
|
||||
* Set an object to which all broadcasts should be sent, rather than iterating over the place
|
||||
* objects and sending to each of them.
|
||||
*
|
||||
* @param object an object to send all broadcasts, or null to send to
|
||||
* each place object instead.
|
||||
* @param object an object to send all broadcasts, or null to send to each place object
|
||||
* instead.
|
||||
*/
|
||||
public void setAlternateBroadcastObject (DObject object)
|
||||
{
|
||||
@@ -91,11 +89,10 @@ public class ChatProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the auto tell responder for the chat provider. Only one auto
|
||||
* responder is allowed. <em>Note:</em> this only works for same-server
|
||||
* tells. If the tell is forwarded to another server, no auto-response
|
||||
* opportunity is provided (because we never have both body objects in the
|
||||
* same place).
|
||||
* Set the auto tell responder for the chat provider. Only one auto responder is allowed.
|
||||
* <em>Note:</em> this only works for same-server tells. If the tell is forwarded to another
|
||||
* server, no auto-response opportunity is provided (because we never have both body objects in
|
||||
* the same place).
|
||||
*/
|
||||
public void setTellAutoResponder (TellAutoResponder autoRespond)
|
||||
{
|
||||
@@ -103,9 +100,8 @@ public class ChatProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the tell forwarded for the chat provider. This is used by the
|
||||
* Crowd peer services to forward tells between servers in a multi-server
|
||||
* cluster.
|
||||
* Configures the tell forwarded for the chat provider. This is used by the Crowd peer services
|
||||
* to forward tells between servers in a multi-server cluster.
|
||||
*/
|
||||
public void setTellForwarder (TellForwarder forwarder)
|
||||
{
|
||||
@@ -113,21 +109,18 @@ public class ChatProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the chat services and registers a chat provider with
|
||||
* the invocation manager.
|
||||
* Initializes the chat services and registers a chat provider with the invocation manager.
|
||||
*/
|
||||
public void init (InvocationManager invmgr, DObjectManager omgr)
|
||||
{
|
||||
// register a chat provider with the invocation manager
|
||||
invmgr.registerDispatcher(new ChatDispatcher(this), true);
|
||||
invmgr.registerDispatcher(new ChatDispatcher(this), CrowdCodes.CROWD_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from a client to deliver a tell message to
|
||||
* another client.
|
||||
* Processes a request from a client to deliver a tell message to another client.
|
||||
*/
|
||||
public void tell (ClientObject caller, Name target, String message,
|
||||
TellListener listener)
|
||||
public void tell (ClientObject caller, Name target, String message, TellListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
// ensure that the caller has normal chat privileges
|
||||
@@ -142,8 +135,7 @@ public class ChatProvider
|
||||
|
||||
// inform the auto-responder if needed
|
||||
BodyObject targobj;
|
||||
if (_autoRespond != null &&
|
||||
(targobj = CrowdServer.lookupBody(target)) != null) {
|
||||
if (_autoRespond != null && (targobj = CrowdServer.lookupBody(target)) != null) {
|
||||
_autoRespond.sentTell(source, targobj, message);
|
||||
}
|
||||
}
|
||||
@@ -151,8 +143,7 @@ public class ChatProvider
|
||||
/**
|
||||
* Processes a {@link ChatService#broadcast} request.
|
||||
*/
|
||||
public void broadcast (ClientObject caller, String message,
|
||||
InvocationListener listener)
|
||||
public void broadcast (ClientObject caller, String message, InvocationListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
// make sure the requesting user has broadcast privileges
|
||||
@@ -170,20 +161,19 @@ public class ChatProvider
|
||||
public void away (ClientObject caller, String message)
|
||||
{
|
||||
BodyObject body = (BodyObject)caller;
|
||||
// we modify this field via an invocation service request because
|
||||
// a body object is not modifiable by the client
|
||||
// we modify this field via an invocation service request because a body object is not
|
||||
// modifiable by the client
|
||||
body.setAwayMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast the specified message to all places in the game.
|
||||
*
|
||||
* @param from the user the broadcast is from, or null to send the message
|
||||
* as a system message.
|
||||
* @param from the user the broadcast is from, or null to send the message as a system message.
|
||||
* @param bundle the bundle, or null if the message needs no translation.
|
||||
* @param msg the content of the message to broadcast.
|
||||
* @param attention if true, the message is sent as ATTENTION level,
|
||||
* otherwise as INFO. Ignored if from is non-null.
|
||||
* @param attention if true, the message is sent as ATTENTION level, otherwise as INFO. Ignored
|
||||
* if from is non-null.
|
||||
*/
|
||||
public void broadcast (Name from, String bundle, String msg,
|
||||
boolean attention)
|
||||
@@ -203,12 +193,10 @@ public class ChatProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers a tell message to the specified target and notifies the
|
||||
* supplied listener of the result. It is assumed that the teller has
|
||||
* already been permissions checked.
|
||||
* Delivers a tell message to the specified target and notifies the supplied listener of the
|
||||
* result. It is assumed that the teller has already been permissions checked.
|
||||
*/
|
||||
public void deliverTell (UserMessage message, Name target,
|
||||
TellListener listener)
|
||||
public void deliverTell (UserMessage message, Name target, TellListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
// make sure the target user is online
|
||||
@@ -225,8 +213,7 @@ public class ChatProvider
|
||||
if (tobj.status == OccupantInfo.DISCONNECTED) {
|
||||
String errmsg = MessageBundle.compose(
|
||||
USER_DISCONNECTED, TimeUtil.getTimeOrderString(
|
||||
System.currentTimeMillis() - tobj.statusTime,
|
||||
TimeUtil.SECOND));
|
||||
System.currentTimeMillis() - tobj.statusTime, TimeUtil.SECOND));
|
||||
throw new InvocationException(errmsg);
|
||||
}
|
||||
|
||||
@@ -246,9 +233,9 @@ public class ChatProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers a tell notification to the specified target player. It is
|
||||
* assumed that the message is coming from some server entity and need not
|
||||
* be permissions checked or notified of the result.
|
||||
* Delivers a tell notification to the specified target player. It is assumed that the message
|
||||
* is coming from some server entity and need not be permissions checked or notified of the
|
||||
* result.
|
||||
*/
|
||||
public void deliverTell (BodyObject target, UserMessage message)
|
||||
{
|
||||
@@ -269,8 +256,8 @@ public class ChatProvider
|
||||
/**
|
||||
* Direct a broadcast to the specified object.
|
||||
*/
|
||||
protected void broadcastTo (DObject object, Name from, String bundle,
|
||||
String msg, boolean attention)
|
||||
protected void broadcastTo (DObject object, Name from, String bundle, String msg,
|
||||
boolean attention)
|
||||
{
|
||||
if (from == null) {
|
||||
if (attention) {
|
||||
@@ -280,8 +267,7 @@ public class ChatProvider
|
||||
}
|
||||
|
||||
} else {
|
||||
SpeakProvider.sendSpeak(object, from, bundle, msg,
|
||||
BROADCAST_MODE);
|
||||
SpeakProvider.sendSpeak(object, from, bundle, msg, BROADCAST_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.threerings.presents.dobj.Subscriber;
|
||||
|
||||
import com.threerings.crowd.Log;
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.CrowdCodes;
|
||||
import com.threerings.crowd.data.LocationCodes;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
@@ -416,12 +417,17 @@ public class LocationDirector extends BasicDirector
|
||||
_lservice = null;
|
||||
}
|
||||
|
||||
@Override // from BasicDirector
|
||||
protected void registerServices (Client client)
|
||||
{
|
||||
client.addServiceGroup(CrowdCodes.CROWD_GROUP);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void fetchServices (Client client)
|
||||
{
|
||||
// obtain our service handle
|
||||
_lservice = (LocationService)
|
||||
client.requireService(LocationService.class);
|
||||
_lservice = (LocationService)client.requireService(LocationService.class);
|
||||
}
|
||||
|
||||
protected void gotBodyObject (BodyObject clobj)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 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.data;
|
||||
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
|
||||
/**
|
||||
* Codes and constants global to the Crowd services.
|
||||
*/
|
||||
public interface CrowdCodes extends InvocationCodes
|
||||
{
|
||||
/** Defines our invocation services group. */
|
||||
public static final String CROWD_GROUP = "crowd";
|
||||
}
|
||||
@@ -99,8 +99,7 @@ public class CrowdPeerManager extends PeerManager
|
||||
|
||||
// unregister our invocation service
|
||||
if (_nodeobj != null) {
|
||||
CrowdServer.invmgr.clearDispatcher(
|
||||
((CrowdNodeObject)_nodeobj).crowdPeerService);
|
||||
CrowdServer.invmgr.clearDispatcher(((CrowdNodeObject)_nodeobj).crowdPeerService);
|
||||
}
|
||||
|
||||
// clear our tell forwarder registration
|
||||
@@ -136,7 +135,7 @@ public class CrowdPeerManager extends PeerManager
|
||||
CrowdNodeObject cnobj = (CrowdNodeObject)_nodeobj;
|
||||
cnobj.setCrowdPeerService(
|
||||
(CrowdPeerMarshaller)CrowdServer.invmgr.registerDispatcher(
|
||||
new CrowdPeerDispatcher(this), false));
|
||||
new CrowdPeerDispatcher(this)));
|
||||
|
||||
// register ourselves as a tell forwarder
|
||||
CrowdServer.chatprov.setTellForwarder(this);
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.threerings.presents.server.InvocationProvider;
|
||||
|
||||
import com.threerings.crowd.Log;
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.CrowdCodes;
|
||||
import com.threerings.crowd.data.OccupantInfo;
|
||||
|
||||
/**
|
||||
@@ -54,7 +55,7 @@ public class BodyProvider
|
||||
public static void init (InvocationManager invmgr)
|
||||
{
|
||||
// register a provider instance
|
||||
invmgr.registerDispatcher(new BodyDispatcher(new BodyProvider()), true);
|
||||
invmgr.registerDispatcher(new BodyDispatcher(new BodyProvider()), CrowdCodes.CROWD_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,35 +59,28 @@ import com.threerings.crowd.chat.server.SpeakDispatcher;
|
||||
import com.threerings.crowd.chat.server.SpeakProvider;
|
||||
|
||||
/**
|
||||
* The place manager is the server-side entity that handles all
|
||||
* place-related interaction. It subscribes to the place object and reacts
|
||||
* to message and other events. Behavior specific to a place (or class of
|
||||
* places) should live in the place manager. An intelligently constructed
|
||||
* hierarchy of place manager classes working in concert with invocation
|
||||
* services should provide the majority of the server-side functionality
|
||||
* of an application built on the Presents platform.
|
||||
* The place manager is the server-side entity that handles all place-related interaction. It
|
||||
* subscribes to the place object and reacts to message and other events. Behavior specific to a
|
||||
* place (or class of places) should live in the place manager. An intelligently constructed
|
||||
* hierarchy of place manager classes working in concert with invocation services should provide
|
||||
* the majority of the server-side functionality of an application built on the Presents platform.
|
||||
*
|
||||
* <p> The base place manager class takes care of the necessary
|
||||
* interactions with the place registry to manage place registration. It
|
||||
* handles the place-related component of chatting. It also provides the
|
||||
* basis for place-based access control.
|
||||
* <p> The base place manager class takes care of the necessary interactions with the place
|
||||
* registry to manage place registration. It handles the place-related component of chatting. It
|
||||
* also provides the basis for place-based access control.
|
||||
*
|
||||
* <p> A derived class is expected to handle initialization, cleanup and
|
||||
* operational functionality via the calldown functions {@link #didInit},
|
||||
* {@link #didStartup}, and {@link #didShutdown} as well as through event
|
||||
* listeners.
|
||||
* <p> A derived class is expected to handle initialization, cleanup and operational functionality
|
||||
* via the calldown functions {@link #didInit}, {@link #didStartup}, and {@link #didShutdown} as
|
||||
* well as through event listeners.
|
||||
*/
|
||||
public class PlaceManager
|
||||
implements MessageListener, OidListListener, ObjectDeathListener,
|
||||
SpeakProvider.SpeakerValidator
|
||||
implements MessageListener, OidListListener, ObjectDeathListener, SpeakProvider.SpeakerValidator
|
||||
{
|
||||
/**
|
||||
* An interface used to allow the registration of standard message handlers
|
||||
* to be invoked by the place manager when particular types of message
|
||||
* events are received.
|
||||
* An interface used to allow the registration of standard message handlers to be invoked by
|
||||
* the place manager when particular types of message events are received.
|
||||
*
|
||||
* @deprecated Use dynamically bound methods instead. See {@link
|
||||
* DynamicListener}.
|
||||
* @deprecated Use dynamically bound methods instead. See {@link DynamicListener}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static interface MessageHandler
|
||||
@@ -96,8 +89,7 @@ public class PlaceManager
|
||||
* Invokes this message handler on the supplied event.
|
||||
*
|
||||
* @param event the message event received.
|
||||
* @param pmgr the place manager for which the message is being
|
||||
* handled.
|
||||
* @param pmgr the place manager for which the message is being handled.
|
||||
*/
|
||||
public void handleEvent (MessageEvent event, PlaceManager pmgr);
|
||||
}
|
||||
@@ -119,9 +111,8 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the occupant info record for the user with the specified
|
||||
* body oid, if they are an occupant of this room. Returns null
|
||||
* otherwise.
|
||||
* Returns the occupant info record for the user with the specified body oid, if they are an
|
||||
* occupant of this room. Returns null otherwise.
|
||||
*/
|
||||
public OccupantInfo getOccupantInfo (int bodyOid)
|
||||
{
|
||||
@@ -129,8 +120,7 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the supplied occupant operation to each occupant currently
|
||||
* present in this place.
|
||||
* Applies the supplied occupant operation to each occupant currently present in this place.
|
||||
*/
|
||||
public void applyToOccupants (OccupantOp op)
|
||||
{
|
||||
@@ -143,11 +133,10 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the occupant info for this room occupant. <em>Note:</em>
|
||||
* This must be used rather than setting the occupant info directly to
|
||||
* avoid possible complications due to rapid fire changes to a user's
|
||||
* occupant info. The occupant info record supplied to this method
|
||||
* must be one returned from {@link #getOccupantInfo}. For example:
|
||||
* Updates the occupant info for this room occupant. <em>Note:</em> This must be used rather
|
||||
* than setting the occupant info directly to avoid possible complications due to rapid fire
|
||||
* changes to a user's occupant info. The occupant info record supplied to this method must be
|
||||
* one returned from {@link #getOccupantInfo}. For example:
|
||||
*
|
||||
* <pre>
|
||||
* OccupantInfo info = _plmgr.getOccupantInfo(bodyOid);
|
||||
@@ -159,17 +148,16 @@ public class PlaceManager
|
||||
{
|
||||
// update the canonical copy
|
||||
_occInfo.put(occInfo.getBodyOid(), occInfo);
|
||||
// clone the canonical copy and send out an event updating the
|
||||
// distributed set with that clone
|
||||
// clone the canonical copy and send out an event updating the distributed set with that
|
||||
// clone
|
||||
_plobj.updateOccupantInfo((OccupantInfo)occInfo.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the place registry after creating this place manager.
|
||||
*/
|
||||
public void init (
|
||||
PlaceRegistry registry, InvocationManager invmgr,
|
||||
DObjectManager omgr, PlaceConfig config)
|
||||
public void init (PlaceRegistry registry, InvocationManager invmgr,
|
||||
DObjectManager omgr, PlaceConfig config)
|
||||
{
|
||||
_registry = registry;
|
||||
_invmgr = invmgr;
|
||||
@@ -181,11 +169,10 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after this place manager has been initialized with its
|
||||
* configuration information but before it has been started up with
|
||||
* its place object reference. Derived classes can override this
|
||||
* function and perform any basic initialization that they desire.
|
||||
* They should of course be sure to call <code>super.didInit()</code>.
|
||||
* Called after this place manager has been initialized with its configuration information but
|
||||
* before it has been started up with its place object reference. Derived classes can override
|
||||
* this function and perform any basic initialization that they desire. They should of course
|
||||
* be sure to call <code>super.didInit()</code>.
|
||||
*/
|
||||
protected void didInit ()
|
||||
{
|
||||
@@ -209,14 +196,12 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an opportunity for place managers to ratify the creation
|
||||
* of a place based on whatever criterion they may require (based on
|
||||
* information available to the manager at this post-init() but
|
||||
* pre-startup() phase of initialization).
|
||||
* Provides an opportunity for place managers to ratify the creation of a place based on
|
||||
* whatever criterion they may require (based on information available to the manager at this
|
||||
* post-init() but pre-startup() phase of initialization).
|
||||
*
|
||||
* @return If a permissions check is to fail, the manager should
|
||||
* return a translatable string explaining the failure.
|
||||
* <code>null</code> should be returned if initialization is to be
|
||||
* @return If a permissions check is to fail, the manager should return a translatable string
|
||||
* explaining the failure. <code>null</code> should be returned if initialization is to be
|
||||
* allowed to proceed.
|
||||
*/
|
||||
public String checkPermissions ()
|
||||
@@ -225,19 +210,18 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the place manager after the place object has been
|
||||
* successfully created.
|
||||
* Called by the place manager after the place object has been successfully created.
|
||||
*/
|
||||
public void startup (PlaceObject plobj)
|
||||
{
|
||||
// keep track of this
|
||||
_plobj = plobj;
|
||||
|
||||
// we usually want to create and register a speaker service instance
|
||||
// that clients can use to speak in this place
|
||||
// we usually want to create and register a speaker service instance that clients can use
|
||||
// to speak in this place
|
||||
if (shouldCreateSpeakService()) {
|
||||
plobj.setSpeakService((SpeakMarshaller) _invmgr.registerDispatcher(
|
||||
new SpeakDispatcher(new SpeakProvider(plobj, this)), false));
|
||||
plobj.setSpeakService((SpeakMarshaller)_invmgr.registerDispatcher(
|
||||
new SpeakDispatcher(new SpeakProvider(plobj, this))));
|
||||
}
|
||||
|
||||
// we'll need to hear about place object events
|
||||
@@ -255,8 +239,8 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes the place object being managed by this place manager to be
|
||||
* destroyed and the place manager to shut down.
|
||||
* Causes the place object being managed by this place manager to be destroyed and the place
|
||||
* manager to shut down.
|
||||
*/
|
||||
public void shutdown ()
|
||||
{
|
||||
@@ -273,12 +257,10 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an opportunity for the place manager to prevent bodies from
|
||||
* entering.
|
||||
* Provides an opportunity for the place manager to prevent bodies from entering.
|
||||
*
|
||||
* @return <code>null</code> if the body can enter, otherwise a
|
||||
* translatable message explaining the reason the body is blocked
|
||||
* from entering
|
||||
* @return <code>null</code> if the body can enter, otherwise a translatable message explaining
|
||||
* the reason the body is blocked from entering
|
||||
*/
|
||||
public String ratifyBodyEntry (BodyObject body)
|
||||
{
|
||||
@@ -286,12 +268,11 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an {@link OccupantInfo} record for the specified body object and
|
||||
* inserts it into our place object. This is called by the location
|
||||
* services when a body enters a place. If a derived class wishes to
|
||||
* perform custom actions when an occupant is being inserted into a room,
|
||||
* they should override {@link #insertOccupantInfo}, if they want to react
|
||||
* to a body having entered, they should override {@link #bodyEntered}.
|
||||
* Builds an {@link OccupantInfo} record for the specified body object and inserts it into our
|
||||
* place object. This is called by the location services when a body enters a place. If a
|
||||
* derived class wishes to perform custom actions when an occupant is being inserted into a
|
||||
* room, they should override {@link #insertOccupantInfo}, if they want to react to a body
|
||||
* having entered, they should override {@link #bodyEntered}.
|
||||
*/
|
||||
public OccupantInfo buildOccupantInfo (BodyObject body)
|
||||
{
|
||||
@@ -299,8 +280,8 @@ public class PlaceManager
|
||||
// create a new occupant info instance
|
||||
OccupantInfo info = body.createOccupantInfo(_plobj);
|
||||
|
||||
// insert the occupant info into our canonical table; this is done
|
||||
// in a method so that derived classes
|
||||
// insert the occupant info into our canonical table; this is done in a method so that
|
||||
// derived classes
|
||||
insertOccupantInfo(info, body);
|
||||
|
||||
// clone the canonical copy and insert it into the DSet
|
||||
@@ -309,23 +290,21 @@ public class PlaceManager
|
||||
return info;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Failure building occupant info " +
|
||||
"[where=" + where() + ", body=" + body + "].");
|
||||
Log.warning("Failure building occupant info [where=" + where() +
|
||||
", body=" + body + "].");
|
||||
Log.logStackTrace(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a particular message handler instance to be used when
|
||||
* processing message events with the specified name.
|
||||
* Registers a particular message handler instance to be used when processing message events
|
||||
* with the specified name.
|
||||
*
|
||||
* @param name the message name of the message events that should be
|
||||
* handled by this handler.
|
||||
* @param name the message name of the message events that should be handled by this handler.
|
||||
* @param handler the handler to be registered.
|
||||
*
|
||||
* @deprecated Use dynamically bound methods instead. See {@link
|
||||
* DynamicListener}.
|
||||
* @deprecated Use dynamically bound methods instead. See {@link DynamicListener}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void registerMessageHandler (String name, MessageHandler handler)
|
||||
@@ -348,11 +327,10 @@ public class PlaceManager
|
||||
handler.handleEvent(event, this);
|
||||
}
|
||||
|
||||
// the first argument should be the client object of the caller or null
|
||||
// if it is a server originated event
|
||||
// the first argument should be the client object of the caller or null if it is a server
|
||||
// originated event
|
||||
int srcoid = event.getSourceOid();
|
||||
DObject source = (srcoid <= 0) ?
|
||||
null : CrowdServer.omgr.getObject(srcoid);
|
||||
DObject source = (srcoid <= 0) ? null : CrowdServer.omgr.getObject(srcoid);
|
||||
Object[] args = event.getArgs(), nargs;
|
||||
if (args == null) {
|
||||
nargs = new Object[] { source };
|
||||
@@ -391,30 +369,26 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean isValidSpeaker (
|
||||
DObject speakObj, ClientObject speaker, byte mode)
|
||||
public boolean isValidSpeaker (DObject speakObj, ClientObject speaker, byte mode)
|
||||
{
|
||||
// only allow people in the room to speak
|
||||
return _plobj.occupants.contains(speaker.getOid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string that can be used in log messages to identify the
|
||||
* place as sensibly as possible to the developer who has to puzzle
|
||||
* over log output trying to figure out what's going on. Derived place
|
||||
* managers can override this and augment the default value (which is
|
||||
* Returns a string that can be used in log messages to identify the place as sensibly as
|
||||
* possible to the developer who has to puzzle over log output trying to figure out what's
|
||||
* going on. Derived place managers can override this and augment the default value (which is
|
||||
* simply the place object id) with useful identifying information.
|
||||
*/
|
||||
public String where ()
|
||||
{
|
||||
return (_plobj == null) ?
|
||||
StringUtil.shortClassName(this) + ":-1" : _plobj.which();
|
||||
return (_plobj == null) ? StringUtil.shortClassName(this) + ":-1" : _plobj.which();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this manager. Does so in a way
|
||||
* that makes it easier for derived classes to add to the string
|
||||
* representation.
|
||||
* Generates a string representation of this manager. Does so in a way that makes it easier for
|
||||
* derived classes to add to the string representation.
|
||||
*
|
||||
* @see #toString(StringBuilder)
|
||||
*/
|
||||
@@ -428,8 +402,8 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will generally override this method to create a custom
|
||||
* {@link PlaceObject} derivation that contains extra information.
|
||||
* Derived classes will generally override this method to create a custom {@link PlaceObject}
|
||||
* derivation that contains extra information.
|
||||
*/
|
||||
protected PlaceObject createPlaceObject ()
|
||||
{
|
||||
@@ -450,17 +424,16 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if the permissions check failed, to give place managers a
|
||||
* chance to do any cleanup that might be necessary due to their early
|
||||
* initialization or permissions checking code.
|
||||
* Called if the permissions check failed, to give place managers a chance to do any cleanup
|
||||
* that might be necessary due to their early initialization or permissions checking code.
|
||||
*/
|
||||
protected void permissionsFailed ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we should create a speaker service for our place object
|
||||
* so that clients can use it to speak in this place.
|
||||
* @return true if we should create a speaker service for our place object so that clients can
|
||||
* use it to speak in this place.
|
||||
*/
|
||||
protected boolean shouldCreateSpeakService ()
|
||||
{
|
||||
@@ -468,8 +441,8 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an access controller for this place's distributed object, which
|
||||
* by default is {@link CrowdObjectAccess#PLACE}.
|
||||
* Creates an access controller for this place's distributed object, which by default is {@link
|
||||
* CrowdObjectAccess#PLACE}.
|
||||
*/
|
||||
protected AccessController getAccessController ()
|
||||
{
|
||||
@@ -477,10 +450,9 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes should override this (and be sure to call
|
||||
* <code>super.didStartup()</code>) to perform any startup time
|
||||
* initialization. The place object will be available by the time this
|
||||
* method is executed.
|
||||
* Derived classes should override this (and be sure to call <code>super.didStartup()</code>)
|
||||
* to perform any startup time initialization. The place object will be available by the time
|
||||
* this method is executed.
|
||||
*/
|
||||
protected void didStartup ()
|
||||
{
|
||||
@@ -493,10 +465,9 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this place has been destroyed and the place manager has
|
||||
* shut down (via a call to {@link #shutdown}). Derived classes can
|
||||
* override this method and perform any necessary shutdown time
|
||||
* processing.
|
||||
* Called when this place has been destroyed and the place manager has shut down (via a call to
|
||||
* {@link #shutdown}). Derived classes can override this method and perform any necessary
|
||||
* shutdown time processing.
|
||||
*/
|
||||
protected void didShutdown ()
|
||||
{
|
||||
@@ -509,10 +480,9 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an occupant is being added to this place. This will be
|
||||
* before the call to {@link #bodyEntered} and gives the derived class a
|
||||
* chance to set up additional information about the occupant that might
|
||||
* not be tracked in the occupant info.
|
||||
* Called when an occupant is being added to this place. This will be before the call to {@link
|
||||
* #bodyEntered} and gives the derived class a chance to set up additional information about
|
||||
* the occupant that might not be tracked in the occupant info.
|
||||
*/
|
||||
protected void insertOccupantInfo (OccupantInfo info, BodyObject body)
|
||||
{
|
||||
@@ -525,8 +495,7 @@ public class PlaceManager
|
||||
protected void bodyEntered (final int bodyOid)
|
||||
{
|
||||
if (Log.log.getLevel() == Level.FINE) {
|
||||
Log.debug("Body entered [where=" + where() +
|
||||
", oid=" + bodyOid + "].");
|
||||
Log.debug("Body entered [where=" + where() + ", oid=" + bodyOid + "].");
|
||||
}
|
||||
|
||||
// let our delegates know what's up
|
||||
@@ -546,13 +515,11 @@ public class PlaceManager
|
||||
protected void bodyLeft (final int bodyOid)
|
||||
{
|
||||
if (Log.log.getLevel() == Level.FINE) {
|
||||
Log.debug("Body left [where=" + where() +
|
||||
", oid=" + bodyOid + "].");
|
||||
Log.debug("Body left [where=" + where() + ", oid=" + bodyOid + "].");
|
||||
}
|
||||
|
||||
// if their occupant info hasn't been removed (which may be the
|
||||
// case if they logged off rather than left via a MoveTo request),
|
||||
// we need to get it on out of here
|
||||
// if their occupant info hasn't been removed (which may be the case if they logged off
|
||||
// rather than left via a MoveTo request), we need to get it on out of here
|
||||
Integer key = Integer.valueOf(bodyOid);
|
||||
if (_plobj.occupantInfo.containsKey(key)) {
|
||||
_plobj.removeFromOccupantInfo(key);
|
||||
@@ -575,8 +542,7 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the location should be marked as empty and potentially
|
||||
* shutdown.
|
||||
* Returns whether the location should be marked as empty and potentially shutdown.
|
||||
*/
|
||||
protected boolean shouldDeclareEmpty (OccupantInfo leaver)
|
||||
{
|
||||
@@ -597,10 +563,9 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we transition from having bodies in the place to not
|
||||
* having any bodies in the place. Some places may take this as a sign
|
||||
* to pack it in, others may wish to stick around. In any case, they
|
||||
* can override this method to do their thing.
|
||||
* Called when we transition from having bodies in the place to not having any bodies in the
|
||||
* place. Some places may take this as a sign to pack it in, others may wish to stick
|
||||
* around. In any case, they can override this method to do their thing.
|
||||
*/
|
||||
protected void placeBecameEmpty ()
|
||||
{
|
||||
@@ -646,9 +611,9 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the period (in milliseconds) of emptiness after which this
|
||||
* place manager will unload itself and shutdown. Returning
|
||||
* <code>0</code> indicates that the place should never be shutdown.
|
||||
* Returns the period (in milliseconds) of emptiness after which this place manager will unload
|
||||
* itself and shutdown. Returning <code>0</code> indicates that the place should never be
|
||||
* shutdown.
|
||||
*/
|
||||
protected long idleUnloadPeriod ()
|
||||
{
|
||||
@@ -656,9 +621,8 @@ public class PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* An extensible way to add to the string representation of this
|
||||
* class. Override this (being sure to call super) and append your
|
||||
* info to the buffer.
|
||||
* An extensible way to add to the string representation of this class. Override this (being
|
||||
* sure to call super) and append your info to the buffer.
|
||||
*/
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
@@ -699,8 +663,7 @@ public class PlaceManager
|
||||
/** A reference to the place registry with which we're registered. */
|
||||
protected PlaceRegistry _registry;
|
||||
|
||||
/** The invocation manager with whom we register our game invocation
|
||||
* services. */
|
||||
/** The invocation manager with whom we register our game invocation services. */
|
||||
protected InvocationManager _invmgr;
|
||||
|
||||
/** A distributed object manager for doing dobj stuff. */
|
||||
@@ -719,12 +682,10 @@ public class PlaceManager
|
||||
protected ArrayList<PlaceManagerDelegate> _delegates;
|
||||
|
||||
/** Used to keep a canonical copy of the occupant info records. */
|
||||
protected HashIntMap<OccupantInfo> _occInfo =
|
||||
new HashIntMap<OccupantInfo>();
|
||||
protected HashIntMap<OccupantInfo> _occInfo = new HashIntMap<OccupantInfo>();
|
||||
|
||||
/** The interval currently registered to shut this place
|
||||
* down after a certain period of idility, or null if no
|
||||
* interval is currently registered. */
|
||||
/** The interval currently registered to shut this place down after a certain period of
|
||||
* idility, or null if no interval is currently registered. */
|
||||
protected Interval _shutdownInterval;
|
||||
|
||||
/** Used to do method lookup magic when we receive message events. */
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationManager;
|
||||
|
||||
import com.threerings.crowd.Log;
|
||||
import com.threerings.crowd.data.CrowdCodes;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
@@ -59,7 +60,7 @@ public class PlaceRegistry
|
||||
{
|
||||
// create and register our location provider
|
||||
locprov = new LocationProvider(invmgr, omgr, this);
|
||||
invmgr.registerDispatcher(new LocationDispatcher(locprov), true);
|
||||
invmgr.registerDispatcher(new LocationDispatcher(locprov), CrowdCodes.CROWD_GROUP);
|
||||
|
||||
// we'll need these later
|
||||
_omgr = omgr;
|
||||
|
||||
@@ -24,19 +24,17 @@ package com.threerings.presents.client;
|
||||
import com.threerings.presents.util.PresentsContext;
|
||||
|
||||
/**
|
||||
* Handles functionality common to nearly all client directors. They
|
||||
* generally need to be session observers so that they can set themselves
|
||||
* up when the client logs on (by overriding {@link #clientDidLogon}) and
|
||||
* clean up after themselves when the client logs off (by overriding
|
||||
* {@link #clientDidLogoff}).
|
||||
* Handles functionality common to nearly all client directors. They generally need to be session
|
||||
* observers so that they can set themselves up when the client logs on (by overriding {@link
|
||||
* #clientDidLogon}) and clean up after themselves when the client logs off (by overriding {@link
|
||||
* #clientDidLogoff}).
|
||||
*/
|
||||
public class BasicDirector
|
||||
implements SessionObserver
|
||||
{
|
||||
/**
|
||||
* Derived directors will need to provide the basic director with a
|
||||
* context that it can use to register itself with the necessary
|
||||
* entities.
|
||||
* Derived directors will need to provide the basic director with a context that it can use to
|
||||
* register itself with the necessary entities.
|
||||
*/
|
||||
protected BasicDirector (PresentsContext ctx)
|
||||
{
|
||||
@@ -56,6 +54,12 @@ public class BasicDirector
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void clientWillLogon (Client client)
|
||||
{
|
||||
registerServices(client);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void clientDidLogon (Client client)
|
||||
{
|
||||
@@ -85,8 +89,7 @@ public class BasicDirector
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not this director is available in standalone mode
|
||||
* (defaults to false).
|
||||
* Checks whether or not this director is available in standalone mode (defaults to false).
|
||||
*/
|
||||
public boolean isAvailableInStandalone ()
|
||||
{
|
||||
@@ -102,8 +105,7 @@ public class BasicDirector
|
||||
}
|
||||
|
||||
/**
|
||||
* If this director is not currently available, throws a
|
||||
* {@link RuntimeException}.
|
||||
* If this director is not currently available, throws a {@link RuntimeException}.
|
||||
*/
|
||||
protected void assertAvailable ()
|
||||
{
|
||||
@@ -114,20 +116,27 @@ public class BasicDirector
|
||||
}
|
||||
|
||||
/**
|
||||
* Called in three circumstances: when a director is created and we've
|
||||
* already logged on; when we first log on and when the client object
|
||||
* changes after we've already logged on.
|
||||
* Called in three circumstances: when a director is created and we've already logged on; when
|
||||
* we first log on and when the client object changes after we've already logged on.
|
||||
*/
|
||||
protected void clientObjectUpdated (Client client)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived directors can override this method and obtain any services
|
||||
* they'll need during their operation via calls to {@link
|
||||
* Client#getService}. If the director is available, it will automatically
|
||||
* be called when the client logs on or when the director is constructed
|
||||
* if it is constructed after the client is already logged on.
|
||||
* If a director makes use of bootstrap invocation services which are part of a bootstrap
|
||||
* service group, it should register interest in that group here with a call to {@link
|
||||
* Client#addServiceGroup}.
|
||||
*/
|
||||
protected void registerServices (Client client)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived directors can override this method and obtain any services they'll need during their
|
||||
* operation via calls to {@link Client#getService}. If the director is available, it will
|
||||
* automatically be called when the client logs on or when the director is constructed if it is
|
||||
* constructed after the client is already logged on.
|
||||
*/
|
||||
protected void fetchServices (Client client)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.samskivert.util.RunQueue;
|
||||
|
||||
import com.threerings.presents.Log;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
import com.threerings.presents.dobj.DObjectManager;
|
||||
import com.threerings.presents.net.AuthResponseData;
|
||||
import com.threerings.presents.net.BootstrapData;
|
||||
@@ -44,8 +45,7 @@ import com.threerings.presents.net.PongResponse;
|
||||
*/
|
||||
public class Client
|
||||
{
|
||||
/** The default ports on which the server listens for client
|
||||
* connections. */
|
||||
/** The default ports on which the server listens for client connections. */
|
||||
public static final int[] DEFAULT_SERVER_PORTS = { 47624 };
|
||||
|
||||
/**
|
||||
@@ -193,16 +193,6 @@ public class Client
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this client as interested in the specified bootstrap services group. Any services
|
||||
* registered as bootstrap services with the supplied group name will be included in this
|
||||
* clients bootstrap services set. This must be called before {@link #logon}.
|
||||
*/
|
||||
public void addBootstrapGroup (String group)
|
||||
{
|
||||
_bootGroups.add(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated with our authentication response. Users of the Presents system
|
||||
* may wish to communicate authentication related information to their client by extending and
|
||||
@@ -269,6 +259,16 @@ public class Client
|
||||
return _invdir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this client as interested in the specified bootstrap services group. Any services
|
||||
* registered as bootstrap services with the supplied group name will be included in this
|
||||
* clients bootstrap services set. This must be called before {@link #logon}.
|
||||
*/
|
||||
public void addServiceGroup (String group)
|
||||
{
|
||||
_bootGroups.add(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first bootstrap service that could be located that implements the supplied
|
||||
* {@link InvocationService} derivation. <code>null</code> is returned if no such service
|
||||
@@ -281,8 +281,7 @@ public class Client
|
||||
}
|
||||
int scount = _bstrap.services.size();
|
||||
for (int ii = 0; ii < scount; ii++) {
|
||||
InvocationService service = (InvocationService)
|
||||
_bstrap.services.get(ii);
|
||||
InvocationService service = (InvocationService)_bstrap.services.get(ii);
|
||||
if (sclass.isInstance(service)) {
|
||||
return service;
|
||||
}
|
||||
@@ -300,8 +299,7 @@ public class Client
|
||||
InvocationService isvc = getService(sclass);
|
||||
if (isvc == null) {
|
||||
throw new RuntimeException(
|
||||
sclass.getName() + " isn't available. " +
|
||||
"I can't bear to go on.");
|
||||
sclass.getName() + " isn't available. I can't bear to go on.");
|
||||
}
|
||||
return isvc;
|
||||
}
|
||||
@@ -744,7 +742,9 @@ public class Client
|
||||
protected BootstrapData _bstrap;
|
||||
|
||||
/** The set of bootstrap service groups this client cares about. */
|
||||
protected HashSet<String> _bootGroups = new HashSet<String>();
|
||||
protected HashSet<String> _bootGroups = new HashSet<String>(); {
|
||||
_bootGroups.add(InvocationCodes.GLOBAL_GROUP);
|
||||
}
|
||||
|
||||
/** Manages invocation services. */
|
||||
protected InvocationDirector _invdir = new InvocationDirector();
|
||||
|
||||
@@ -32,6 +32,11 @@ package com.threerings.presents.client;
|
||||
*/
|
||||
public class ClientAdapter implements ClientObserver
|
||||
{
|
||||
// documentation inherited
|
||||
public void clientWillLogon (Client client)
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clientDidLogon (Client client)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,11 @@ package com.threerings.presents.client;
|
||||
*/
|
||||
public interface SessionObserver
|
||||
{
|
||||
/**
|
||||
* Called immediately before a logon is attempted.
|
||||
*/
|
||||
public void clientWillLogon (Client client);
|
||||
|
||||
/**
|
||||
* Called after the client successfully connected to and authenticated
|
||||
* with the server. The entire object system is up and running by the
|
||||
|
||||
@@ -29,6 +29,10 @@ package com.threerings.presents.data;
|
||||
*/
|
||||
public interface InvocationCodes
|
||||
{
|
||||
/** Defines a global invocation services group that can be used by clients and services that do
|
||||
* not care to make a distinction between groups of invocation services. */
|
||||
public static final String GLOBAL_GROUP = "presents";
|
||||
|
||||
/** An error code returned to clients when a service cannot be performed because of some
|
||||
* internal server error that we couldn't explain in any meaningful way (things like null
|
||||
* pointer exceptions). */
|
||||
|
||||
@@ -160,8 +160,7 @@ public class PeerManager
|
||||
|
||||
// set the invocation service
|
||||
_nodeobj.setPeerService(
|
||||
(PeerMarshaller)PresentsServer.invmgr.registerDispatcher(
|
||||
new PeerDispatcher(this), false));
|
||||
(PeerMarshaller)PresentsServer.invmgr.registerDispatcher(new PeerDispatcher(this)));
|
||||
|
||||
// register ourselves as a client observer
|
||||
PresentsServer.clmgr.addClientObserver(this);
|
||||
@@ -668,6 +667,12 @@ public class PeerManager
|
||||
log.warning("Peer connection failed " + _record + ": " + cause);
|
||||
}
|
||||
|
||||
// documentation inherited from interface ClientObserver
|
||||
public void clientWillLogon (Client client)
|
||||
{
|
||||
// nothing doing
|
||||
}
|
||||
|
||||
// documentation inherited from interface ClientObserver
|
||||
public void clientDidLogon (Client client)
|
||||
{
|
||||
|
||||
@@ -62,9 +62,6 @@ import java.util.HashMap;
|
||||
public class InvocationManager
|
||||
implements EventListener
|
||||
{
|
||||
/** Defines the name of the global bootstrap group. */
|
||||
public static final String GLOBAL_BOOTSTRAP_GROUP = "global";
|
||||
|
||||
/** A mapping from bootstrap group to lists of services that are to be provided to clients at
|
||||
* boot time. Don't mess with these lists! */
|
||||
public HashMap<String,StreamableArrayList<InvocationMarshaller>> bootlists =
|
||||
@@ -100,13 +97,10 @@ public class InvocationManager
|
||||
* send requests to the provider for whom the dispatcher is proxying.
|
||||
*
|
||||
* @param dispatcher the dispatcher to be registered.
|
||||
* @param bootstrap if true, the service instance will be added to the list of invocation
|
||||
* service objects provided to the client in the bootstrap data.
|
||||
*/
|
||||
public InvocationMarshaller registerDispatcher (
|
||||
InvocationDispatcher dispatcher, boolean bootstrap)
|
||||
public InvocationMarshaller registerDispatcher (InvocationDispatcher dispatcher)
|
||||
{
|
||||
return registerDispatcher(dispatcher, bootstrap ? GLOBAL_BOOTSTRAP_GROUP : null);
|
||||
return registerDispatcher(dispatcher, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,8 +134,7 @@ public class InvocationManager
|
||||
list.add(marsh);
|
||||
}
|
||||
|
||||
_recentRegServices.put(Integer.valueOf(invCode),
|
||||
marsh.getClass().getName());
|
||||
_recentRegServices.put(Integer.valueOf(invCode), marsh.getClass().getName());
|
||||
|
||||
// Log.info("Registered service [marsh=" + marsh + "].");
|
||||
return marsh;
|
||||
@@ -292,8 +285,7 @@ public class InvocationManager
|
||||
/** The distributed object manager with which we're working. */
|
||||
protected RootDObjectManager _omgr;
|
||||
|
||||
/** The object id of the object on which we receive invocation service
|
||||
* requests. */
|
||||
/** The object id of the object on which we receive invocation service requests. */
|
||||
protected int _invoid = -1;
|
||||
|
||||
/** Used to generate monotonically increasing provider ids. */
|
||||
@@ -303,7 +295,7 @@ public class InvocationManager
|
||||
protected HashIntMap<InvocationDispatcher> _dispatchers =
|
||||
new HashIntMap<InvocationDispatcher>();
|
||||
|
||||
/** The text that is appended to the procedure name when automatically
|
||||
* generating a failure response. */
|
||||
/** The text that is appended to the procedure name when automatically generating a failure
|
||||
* response. */
|
||||
protected static final String FAILED_SUFFIX = "Failed";
|
||||
}
|
||||
|
||||
@@ -651,13 +651,9 @@ public class PresentsClient
|
||||
|
||||
// fill in the list of bootstrap services
|
||||
data.services = new StreamableArrayList<InvocationMarshaller>();
|
||||
StreamableArrayList<InvocationMarshaller> list =
|
||||
PresentsServer.invmgr.bootlists.get(InvocationManager.GLOBAL_BOOTSTRAP_GROUP);
|
||||
if (list != null) {
|
||||
data.services.addAll(list);
|
||||
}
|
||||
for (String group : _areq.getBootGroups()) {
|
||||
list = PresentsServer.invmgr.bootlists.get(group);
|
||||
StreamableArrayList<InvocationMarshaller> list =
|
||||
PresentsServer.invmgr.bootlists.get(group);
|
||||
if (list != null) {
|
||||
data.services.addAll(list);
|
||||
}
|
||||
|
||||
@@ -34,17 +34,16 @@ import com.threerings.presents.data.TimeBaseObject;
|
||||
import com.threerings.presents.dobj.RootDObjectManager;
|
||||
|
||||
/**
|
||||
* Provides the server-side of the time base services. The time base
|
||||
* services provide a means by which delta times can be sent over the
|
||||
* network which are expanded based on a shared base time into full time
|
||||
* stamps.
|
||||
* Provides the server-side of the time base services. The time base services provide a means by
|
||||
* which delta times can be sent over the network which are expanded based on a shared base time
|
||||
* into full time stamps.
|
||||
*/
|
||||
public class TimeBaseProvider
|
||||
implements InvocationProvider, TimeBaseCodes
|
||||
{
|
||||
/**
|
||||
* Registers the time provider with the appropriate managers. Called
|
||||
* by the presents server at startup.
|
||||
* Registers the time provider with the appropriate managers. Called by the presents server at
|
||||
* startup.
|
||||
*/
|
||||
public static void init (InvocationManager invmgr, RootDObjectManager omgr)
|
||||
{
|
||||
@@ -53,13 +52,12 @@ public class TimeBaseProvider
|
||||
_omgr = omgr;
|
||||
|
||||
// register a provider instance
|
||||
invmgr.registerDispatcher(
|
||||
new TimeBaseDispatcher(new TimeBaseProvider()), true);
|
||||
invmgr.registerDispatcher(new TimeBaseDispatcher(new TimeBaseProvider()), GLOBAL_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a time base object which can subsequently be fetched by the
|
||||
* client and used to send delta times.
|
||||
* Creates a time base object which can subsequently be fetched by the client and used to send
|
||||
* delta times.
|
||||
*
|
||||
* @param timeBase the name of the time base to create.
|
||||
*
|
||||
@@ -73,8 +71,8 @@ public class TimeBaseProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the named timebase object, or null if no time base object
|
||||
* has been created with that name.
|
||||
* Returns the named timebase object, or null if no time base object has been created with that
|
||||
* name.
|
||||
*/
|
||||
public static TimeBaseObject getTimeBase (String timeBase)
|
||||
{
|
||||
@@ -82,11 +80,9 @@ public class TimeBaseProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from a client to fetch the oid of the specified
|
||||
* time object.
|
||||
* Processes a request from a client to fetch the oid of the specified time object.
|
||||
*/
|
||||
public void getTimeOid (
|
||||
ClientObject source, String timeBase, GotTimeBaseListener listener)
|
||||
public void getTimeOid (ClientObject source, String timeBase, GotTimeBaseListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
// look up the time base object in question
|
||||
|
||||
@@ -100,6 +100,11 @@ public class JabberClient
|
||||
return _ctx;
|
||||
}
|
||||
|
||||
// documentation inherited from interface SessionObserver
|
||||
public void clientWillLogon (Client client)
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited from interface SessionObserver
|
||||
public void clientDidLogon (Client client)
|
||||
{
|
||||
|
||||
@@ -83,6 +83,10 @@ public class TestClient
|
||||
return _main == Thread.currentThread();
|
||||
}
|
||||
|
||||
public void clientWillLogon (Client client)
|
||||
{
|
||||
}
|
||||
|
||||
public void clientDidLogon (Client client)
|
||||
{
|
||||
Log.info("Client did logon [client=" + client + "].");
|
||||
|
||||
@@ -67,6 +67,11 @@ public class TestClient
|
||||
}
|
||||
}
|
||||
|
||||
public void clientWillLogon (Client client)
|
||||
{
|
||||
client.addServiceGroup("test");
|
||||
}
|
||||
|
||||
public void clientDidLogon (Client client)
|
||||
{
|
||||
Log.info("Client did logon [client=" + client + "].");
|
||||
|
||||
@@ -35,7 +35,7 @@ public class TestServer extends PresentsServer
|
||||
super.init();
|
||||
|
||||
// register our test provider
|
||||
invmgr.registerDispatcher(new TestDispatcher(new TestManager()), true);
|
||||
invmgr.registerDispatcher(new TestDispatcher(new TestManager()), "test");
|
||||
|
||||
// create a test object
|
||||
testobj = omgr.registerObject(new TestObject());
|
||||
|
||||
Reference in New Issue
Block a user