From 962326fcaf92b29cf2ebd4586cf1a18675c187d8 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Sat, 21 Jul 2007 00:46:25 +0000 Subject: [PATCH] Revamped the way BodyObject.location is tracked. Now we use an object which can be extended to contain the sceneId by Whirled (Vilya's Whirled, though also Whirled Whirled by extension) so that we don't end up with problems where BodyObject.location changes but BodyObject.sceneId remains stale. This won't impact Yohoho because the Yohoho client is always in a scene, it uses a separate mechanism to track games, whereas Whirled's natural usage is to move between scenes and non-scenes. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4779 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../threerings/crowd/chat/data/ChatMessage.as | 21 ++-- .../crowd/chat/data/SystemMessage.as | 9 +- .../crowd/chat/data/TellFeedbackMessage.as | 24 +++- .../crowd/chat/data/UserSystemMessage.as | 4 +- .../com/threerings/crowd/data/BodyObject.as | 41 ++++--- .../com/threerings/crowd/data/OccupantInfo.as | 9 +- src/as/com/threerings/crowd/data/Place.as | 64 ++++++++++ src/as/com/threerings/crowd/data/TokenRing.as | 4 +- .../threerings/presents/data/ConMgrStats.as | 14 +-- .../com/threerings/crowd/data/BodyObject.java | 57 ++++----- src/java/com/threerings/crowd/data/Place.java | 61 ++++++++++ .../threerings/crowd/server/BodyProvider.java | 32 +++-- .../threerings/crowd/server/CrowdClient.java | 30 ++--- .../crowd/server/LocationProvider.java | 48 ++++---- .../threerings/crowd/server/PlaceManager.java | 9 ++ .../crowd/server/PlaceRegistry.java | 110 ++++++++---------- 16 files changed, 332 insertions(+), 205 deletions(-) create mode 100644 src/as/com/threerings/crowd/data/Place.as create mode 100644 src/java/com/threerings/crowd/data/Place.java diff --git a/src/as/com/threerings/crowd/chat/data/ChatMessage.as b/src/as/com/threerings/crowd/chat/data/ChatMessage.as index 9127de38e..d3f3725d1 100644 --- a/src/as/com/threerings/crowd/chat/data/ChatMessage.as +++ b/src/as/com/threerings/crowd/chat/data/ChatMessage.as @@ -24,7 +24,6 @@ package com.threerings.crowd.chat.data { import flash.utils.getTimer; // function import import com.threerings.util.ClassUtil; -import com.threerings.util.Long; import com.threerings.io.ObjectInputStream; import com.threerings.io.ObjectOutputStream; @@ -42,8 +41,8 @@ public /*abstract*/ class ChatMessage /** The bundle to use when translating this message. */ public var bundle :String; - /** The client side 'localtype' of this chat, set to the type - * registered with an auxiliary source in the ChatDirector. */ + /** The client side 'localtype' of this chat, set to the type registered with an auxiliary + * source in the ChatDirector. */ public var localtype :String; /** The client time that this message was created. */ @@ -67,14 +66,6 @@ public /*abstract*/ class ChatMessage timestamp = getTimer(); } - /** - * Get the appropriate message format for this message. - */ - public function getFormat () :String - { - return null; - } - /** * Generates a string representation of this instance. */ @@ -84,6 +75,14 @@ public /*abstract*/ class ChatMessage " [message=" + message + ", bundle=" + bundle + "]"; } + /** + * Get the appropriate message format for this message. + */ + public function getFormat () :String + { + return null; + } + // from interface Streamable public function readObject (ins :ObjectInputStream) :void { diff --git a/src/as/com/threerings/crowd/chat/data/SystemMessage.as b/src/as/com/threerings/crowd/chat/data/SystemMessage.as index d5bdce08b..f1c53392a 100644 --- a/src/as/com/threerings/crowd/chat/data/SystemMessage.as +++ b/src/as/com/threerings/crowd/chat/data/SystemMessage.as @@ -30,19 +30,16 @@ import com.threerings.io.ObjectOutputStream; */ public class SystemMessage extends ChatMessage { - /** Attention level constant to indicate that this message is merely - * providing the user with information. */ + /** Attention level constant to indicate that this message is merely providing the user with + * information. */ public static const INFO :int = 0; - /** Attention level constant to indicate that this message is the - * result of a user action. */ + /** Attention level constant to indicate that this message is the result of a user action. */ public static const FEEDBACK :int = 1; /** Attention level constant to indicate that some action is required. */ public static const ATTENTION :int = 2; - //---- - /** The attention level of this message. */ public var attentionLevel :int; diff --git a/src/as/com/threerings/crowd/chat/data/TellFeedbackMessage.as b/src/as/com/threerings/crowd/chat/data/TellFeedbackMessage.as index f2c075f6d..5838eb0cb 100644 --- a/src/as/com/threerings/crowd/chat/data/TellFeedbackMessage.as +++ b/src/as/com/threerings/crowd/chat/data/TellFeedbackMessage.as @@ -21,6 +21,8 @@ package com.threerings.crowd.chat.data { +import com.threerings.io.ObjectInputStream; +import com.threerings.io.ObjectOutputStream; import com.threerings.util.Name; /** @@ -34,7 +36,7 @@ public class TellFeedbackMessage extends UserMessage public function TellFeedbackMessage (target :Name, message :String, failed :Boolean = false) { super(target, null, message); - _failed = failed; + _failure = failed; } /** @@ -42,14 +44,28 @@ public class TellFeedbackMessage extends UserMessage */ public function isFailure () :Boolean { - return _failed; + return _failure; } override public function getFormat () :String { - return _failed ? null : "m.told_format"; + return _failure ? null : "m.told_format"; } - protected var _failed :Boolean; + // from interface Streamable + override public function readObject (ins :ObjectInputStream) :void + { + super.readObject(ins); + _failure = ins.readBoolean(); + } + + // from interface Streamable + override public function writeObject (out :ObjectOutputStream) :void + { + super.writeObject(out); + out.writeBoolean(_failure); + } + + protected var _failure :Boolean; } } diff --git a/src/as/com/threerings/crowd/chat/data/UserSystemMessage.as b/src/as/com/threerings/crowd/chat/data/UserSystemMessage.as index b9ebedb0d..a3460654f 100644 --- a/src/as/com/threerings/crowd/chat/data/UserSystemMessage.as +++ b/src/as/com/threerings/crowd/chat/data/UserSystemMessage.as @@ -33,8 +33,7 @@ import com.threerings.io.ObjectOutputStream; */ public class UserSystemMessage extends SystemMessage { - /** The "speaker" of this message, the user that triggered that this - * message be sent to us. */ + /** The "speaker" of this message, the user that triggered that this message be sent to us. */ public var speaker :Name; /** @@ -48,6 +47,7 @@ public class UserSystemMessage extends SystemMessage this.speaker = sender; } + // from interface Streamable override public function readObject (ins :ObjectInputStream) :void { super.readObject(ins); diff --git a/src/as/com/threerings/crowd/data/BodyObject.as b/src/as/com/threerings/crowd/data/BodyObject.as index 992febf35..d76fdab40 100644 --- a/src/as/com/threerings/crowd/data/BodyObject.as +++ b/src/as/com/threerings/crowd/data/BodyObject.as @@ -33,8 +33,7 @@ import com.threerings.io.ObjectInputStream; import com.threerings.io.ObjectOutputStream; /** - * The basic user object class for Crowd users. Bodies have a username, a - * location and a status. + * The basic user object class for Crowd users. Bodies have a username, a location and a status. */ public class BodyObject extends ClientObject { @@ -53,17 +52,17 @@ public class BodyObject extends ClientObject // AUTO-GENERATED: FIELDS END /** - * The username associated with this body object. This should not be used - * directly; in general {@link #getVisibleName} should be used unless you - * specifically know that you want the username. + * The username associated with this body object. This should not be used directly; in general + * {@link #getVisibleName} should be used unless you specifically know that you want the + * username. */ public var username :Name; /** - * The oid of the place currently occupied by this body or -1 if they - * currently occupy no place. + * The oid of the place currently occupied by this body or -1 if they currently occupy no + * place. */ - public var location :int = -1; + public var location :Place; /** * The user's current status ({@link OccupantInfo#ACTIVE}, etc.). @@ -71,21 +70,19 @@ public class BodyObject extends ClientObject public var status :int; /** - * If non-null, this contains a message to be auto-replied whenever - * another user delivers a tell message to this user. + * If non-null, this contains a message to be auto-replied whenever another user delivers a + * tell message to this user. */ public var awayMessage :String; /** - * Checks whether or not this user has access to the specified - * feature. Currently used by the chat system to regulate access to - * chat broadcasts but also forms the basis of an extensible + * Checks whether or not this user has access to the specified feature. Currently used by the + * chat system to regulate access to chat broadcasts but also forms the basis of an extensible * fine-grained permissions system. * - * @return null if the user has access, a fully-qualified translatable - * message string indicating the reason for denial of access (or just - * {@link InvocationCodes#ACCESS_DENIED} if you don't want to be - * specific). + * @return null if the user has access, a fully-qualified translatable message string + * indicating the reason for denial of access (or just {@link InvocationCodes#ACCESS_DENIED} if + * you don't want to be specific). */ public function checkAccess (feature :String, context :Object) :String { @@ -116,6 +113,14 @@ public class BodyObject extends ClientObject return username; } + /** + * Returns the oid of the place occupied by this body or -1 if we occupy no place. + */ + public function getPlaceOid () :int + { + return (location == null) ? -1 : location.placeOid; + } + // // AUTO-GENERATED: METHODS START // /** // * Requests that the username field be set to the @@ -207,7 +212,7 @@ public class BodyObject extends ClientObject super.readObject(ins); username = (ins.readObject() as Name); - location = ins.readInt(); + location = (ins.readObject() as Place); status = ins.readByte(); awayMessage = (ins.readField(String) as String); } diff --git a/src/as/com/threerings/crowd/data/OccupantInfo.as b/src/as/com/threerings/crowd/data/OccupantInfo.as index 8e832fb73..0b2ceda3f 100644 --- a/src/as/com/threerings/crowd/data/OccupantInfo.as +++ b/src/as/com/threerings/crowd/data/OccupantInfo.as @@ -118,11 +118,10 @@ public class OccupantInfo extends SimpleStreamableObject // from interface Streamable override public function writeObject (out :ObjectOutputStream) :void { - throw new Error(); -// super.writeObject(out); -// out.writeObject(new Integer(bodyOid)); -// out.writeObject(username); -// out.writeByte(status); + super.writeObject(out); + out.writeObject(new Integer(bodyOid)); + out.writeObject(username); + out.writeByte(status); } } } diff --git a/src/as/com/threerings/crowd/data/Place.as b/src/as/com/threerings/crowd/data/Place.as new file mode 100644 index 000000000..974ec7eb5 --- /dev/null +++ b/src/as/com/threerings/crowd/data/Place.as @@ -0,0 +1,64 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2007 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.io.ObjectInputStream; +import com.threerings.io.ObjectOutputStream; +import com.threerings.io.SimpleStreamableObject; + +/** + * Contains information on the current place occupied by a body. + */ +public class Place extends SimpleStreamableObject +{ + /** The oid of this place's {@link PlaceObject}. */ + public var placeOid :int; + + /** + * Creates a place with the supplied oid. + */ + public function Place (placeOid :int = 0) + { + this.placeOid = placeOid; + } + + // from Object + public function equals (other :Object) :Boolean + { + return (other is Place) && ((other as Place).placeOid == placeOid); + } + + // from interface Streamable + override public function readObject (ins :ObjectInputStream) :void + { + super.readObject(ins); + placeOid = ins.readInt(); + } + + // from interface Streamable + override public function writeObject (out :ObjectOutputStream) :void + { + super.writeObject(out); + out.writeInt(placeOid); + } +} +} diff --git a/src/as/com/threerings/crowd/data/TokenRing.as b/src/as/com/threerings/crowd/data/TokenRing.as index a69a9fc34..f7b6b1d72 100644 --- a/src/as/com/threerings/crowd/data/TokenRing.as +++ b/src/as/com/threerings/crowd/data/TokenRing.as @@ -31,8 +31,8 @@ import com.threerings.io.SimpleStreamableObject; */ public class TokenRing extends SimpleStreamableObject { - /** Indicates that this user is an administrator and can do things - * like broadcast, shutdown the server and whatnot. */ + /** Indicates that this user is an administrator and can do things like broadcast, shutdown the + * server and whatnot. */ public static const ADMIN :int = (1 << 0); /** diff --git a/src/as/com/threerings/presents/data/ConMgrStats.as b/src/as/com/threerings/presents/data/ConMgrStats.as index d5b579ceb..8cc062bb3 100644 --- a/src/as/com/threerings/presents/data/ConMgrStats.as +++ b/src/as/com/threerings/presents/data/ConMgrStats.as @@ -34,20 +34,18 @@ import com.threerings.util.Long; public class ConMgrStats extends SimpleStreamableObject implements Cloneable { - /** The size of the queue of waiting to auth sockets. This is a snapshot at - * the time the stats are requested. */ + /** The size of the queue of waiting to auth sockets. This is a snapshot at the time the stats + * are requested. */ public var authQueueSize :int; - /** The size of the queue of waiting to die sockets. This is a snapshot at - * the time the stats are requested. */ + /** The size of the queue of waiting to die sockets. This is a snapshot at the time the stats + * are requested. */ public var deathQueueSize :int; - /** The outgoing queue size. This is a snapshot at the time the stats are - * requested. */ + /** The outgoing queue size. This is a snapshot at the time the stats are requested. */ public var outQueueSize :int; - /** The overflow queue size. This is a snapshot at the time the stats are - * requested. */ + /** The overflow queue size. This is a snapshot at the time the stats are requested. */ public var overQueueSize :int; /** The number of connection events since the server started up. */ diff --git a/src/java/com/threerings/crowd/data/BodyObject.java b/src/java/com/threerings/crowd/data/BodyObject.java index e334be3b0..0062fa5f6 100644 --- a/src/java/com/threerings/crowd/data/BodyObject.java +++ b/src/java/com/threerings/crowd/data/BodyObject.java @@ -30,8 +30,7 @@ import com.threerings.crowd.chat.data.ChatCodes; import com.threerings.crowd.chat.data.SpeakObject; /** - * The basic user object class for Crowd users. Bodies have a username, a - * location and a status. + * The basic user object class for Crowd users. Bodies have a username, a location and a status. */ public class BodyObject extends ClientObject implements SpeakObject @@ -51,17 +50,17 @@ public class BodyObject extends ClientObject // AUTO-GENERATED: FIELDS END /** - * The username associated with this body object. This should not be used - * directly; in general {@link #getVisibleName} should be used unless you - * specifically know that you want the username. + * The username associated with this body object. This should not be used directly; in general + * {@link #getVisibleName} should be used unless you specifically know that you want the + * username. */ public Name username; /** - * The oid of the place currently occupied by this body or -1 if they - * currently occupy no place. + * Identifies the place currently occupied by this body. null if they currently occupy no + * place. */ - public int location = -1; + public Place location; /** * The user's current status ({@link OccupantInfo#ACTIVE}, etc.). @@ -69,27 +68,33 @@ public class BodyObject extends ClientObject public byte status; /** - * The time at which the {@link #status} field was last updated. This - * is only available on the server. + * The time at which the {@link #status} field was last updated. This is only available on the + * server. */ public transient long statusTime; /** - * If non-null, this contains a message to be auto-replied whenever - * another user delivers a tell message to this user. + * If non-null, this contains a message to be auto-replied whenever another user delivers a + * tell message to this user. */ public String awayMessage; /** - * Checks whether or not this user has access to the specified - * feature. Currently used by the chat system to regulate access to - * chat broadcasts but also forms the basis of an extensible + * Returns the oid of the place occupied by this body or -1 if we occupy no place. + */ + public int getPlaceOid () + { + return (location == null) ? -1 : location.placeOid; + } + + /** + * Checks whether or not this user has access to the specified feature. Currently used by the + * chat system to regulate access to chat broadcasts but also forms the basis of an extensible * fine-grained permissions system. * - * @return null if the user has access, a fully-qualified translatable - * message string indicating the reason for denial of access (or just - * {@link InvocationCodes#ACCESS_DENIED} if you don't want to be - * specific). + * @return null if the user has access, a fully-qualified translatable message string + * indicating the reason for denial of access (or just {@link InvocationCodes#ACCESS_DENIED} if + * you don't want to be specific). */ public String checkAccess (String feature, Object context) { @@ -112,8 +117,8 @@ public class BodyObject extends ClientObject } /** - * Returns the name that should be displayed to other users and used for - * the chat system. The default is to use {@link #username}. + * Returns the name that should be displayed to other users and used for the chat system. The + * default is to use {@link #username}. */ public Name getVisibleName () { @@ -121,8 +126,8 @@ public class BodyObject extends ClientObject } /** - * Creates a blank occupant info instance that will used to publish - * information about the various bodies occupying a place. + * Creates a blank occupant info instance that will used to publish information about the + * various bodies occupying a place. */ public OccupantInfo createOccupantInfo (PlaceObject placeObject) { @@ -169,11 +174,11 @@ public class BodyObject extends ClientObject * clients) will apply the value change when they received the * attribute changed notification. */ - public void setLocation (int value) + public void setLocation (Place value) { - int ovalue = this.location; + Place ovalue = this.location; requestAttributeChange( - LOCATION, Integer.valueOf(value), Integer.valueOf(ovalue)); + LOCATION, value, ovalue); this.location = value; } diff --git a/src/java/com/threerings/crowd/data/Place.java b/src/java/com/threerings/crowd/data/Place.java new file mode 100644 index 000000000..b24409bd7 --- /dev/null +++ b/src/java/com/threerings/crowd/data/Place.java @@ -0,0 +1,61 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2007 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.io.SimpleStreamableObject; + +/** + * Contains information on the current place occupied by a body. + */ +public class Place extends SimpleStreamableObject +{ + /** The oid of this place's {@link PlaceObject}. */ + public int placeOid; + + /** Used when unserializing. */ + public Place () + { + } + + /** + * Creates a place with the supplied oid. + */ + public Place (int placeOid) + { + this.placeOid = placeOid; + } + + @Override // from Object + public boolean equals (Object other) + { + if (other == null) { + return false; + } + return getClass().equals(other.getClass()) ? placeOid == ((Place)other).placeOid : false; + } + + @Override // from Object + public int hashCode () + { + return placeOid; + } +} diff --git a/src/java/com/threerings/crowd/server/BodyProvider.java b/src/java/com/threerings/crowd/server/BodyProvider.java index 6f3e62564..7593b9820 100644 --- a/src/java/com/threerings/crowd/server/BodyProvider.java +++ b/src/java/com/threerings/crowd/server/BodyProvider.java @@ -30,6 +30,7 @@ import com.threerings.crowd.Log; import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.CrowdCodes; import com.threerings.crowd.data.OccupantInfo; +import com.threerings.crowd.data.Place; /** * Provides the server-side side of the body-related invocation services. @@ -59,8 +60,7 @@ public class BodyProvider } /** - * Handles a request to set the idle state of a client to the - * specified value. + * Handles a request to set the idle state of a client to the specified value. */ public void setIdle (ClientObject caller, boolean idle) throws InvocationException @@ -72,26 +72,23 @@ public class BodyProvider // report NOOP attempts if (bobj.status == nstatus) { - throw new InvocationException( - (idle) ? "m.already_idle" : "m.already_active"); + throw new InvocationException((idle) ? "m.already_idle" : "m.already_active"); } // update their status! - Log.debug("Setting user idle state [user=" + bobj.username + - ", status=" + nstatus + "]."); + 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). + * 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, int locationId, - OccupantInfoOp occop) + public static void updateOccupantInfo (BodyObject body, Place location, OccupantInfoOp occop) { - PlaceManager pmgr = CrowdServer.plreg.getPlaceManager(locationId); + PlaceManager pmgr = (location == null) ? null : + CrowdServer.plreg.getPlaceManager(location.placeOid); if (pmgr == null) { return; } @@ -103,11 +100,10 @@ public class BodyProvider } /** - * Updates the connection status for the given body object's occupant - * info in the specified location. + * Updates the connection status for the given body object's occupant info in the specified + * location. */ - public static void updateOccupantStatus ( - BodyObject body, int locationId, final byte status) + public static void updateOccupantStatus (BodyObject body, Place location, final byte status) { // no need to NOOP if (body.status != status) { @@ -116,7 +112,7 @@ public class BodyProvider body.statusTime = System.currentTimeMillis(); } - updateOccupantInfo(body, locationId, new OccupantInfoOp() { + updateOccupantInfo(body, location, new OccupantInfoOp() { public boolean update (OccupantInfo info) { if (info.status != status) { info.status = status; diff --git a/src/java/com/threerings/crowd/server/CrowdClient.java b/src/java/com/threerings/crowd/server/CrowdClient.java index 84d9ef897..272006506 100644 --- a/src/java/com/threerings/crowd/server/CrowdClient.java +++ b/src/java/com/threerings/crowd/server/CrowdClient.java @@ -31,8 +31,7 @@ import com.threerings.crowd.data.OccupantInfo; import com.threerings.crowd.server.CrowdServer; /** - * The crowd client extends the presents client with crowd-specific client - * handling. + * The crowd client extends the presents client with crowd-specific client handling. */ public class CrowdClient extends PresentsClient { @@ -44,8 +43,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); + BodyProvider.updateOccupantStatus(bobj, bobj.location, OccupantInfo.DISCONNECTED); } } @@ -57,12 +55,10 @@ public class CrowdClient extends PresentsClient if (_clobj != null) { // note that the user's active once more BodyObject bobj = (BodyObject)_clobj; - BodyProvider.updateOccupantStatus( - bobj, bobj.location, OccupantInfo.ACTIVE); + BodyProvider.updateOccupantStatus(bobj, bobj.location, OccupantInfo.ACTIVE); } else { - Log.warning("Session resumed but we have no client object!? " + - "[client=" + this + "]."); + Log.warning("Session resumed but we have no client object!? [client=" + this + "]."); } } @@ -73,13 +69,12 @@ public class CrowdClient extends PresentsClient BodyObject body = (BodyObject)_clobj; - // clear out our location so that anyone listening for such things - // will know that we've left + // clear out our location so that anyone listening will know that we've left clearLocation(body); - // reset our status in case this object remains around until they - // start their next session (which could happen very soon) - BodyProvider.updateOccupantStatus(body, -1, OccupantInfo.ACTIVE); + // 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); // clear our chat history if (body != null) { @@ -88,11 +83,10 @@ public class CrowdClient extends PresentsClient } /** - * When the user ends their session, this method is called to clear - * out any location they might occupy. The default implementation - * takes care of standard crowd location occupancy, but users of other - * services may which to override this method and clear the user out - * of a scene, zone or other location-derived occupancy. + * When the user ends their session, this method is called to clear out any location they might + * occupy. The default implementation takes care of standard crowd location occupancy, but + * users of other services may which to override this method and clear the user out of a scene, + * zone or other location-derived occupancy. */ protected void clearLocation (BodyObject bobj) { diff --git a/src/java/com/threerings/crowd/server/LocationProvider.java b/src/java/com/threerings/crowd/server/LocationProvider.java index 0984772f8..19fc927e4 100644 --- a/src/java/com/threerings/crowd/server/LocationProvider.java +++ b/src/java/com/threerings/crowd/server/LocationProvider.java @@ -34,6 +34,7 @@ import com.threerings.crowd.Log; import com.threerings.crowd.client.LocationService; import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.LocationCodes; +import com.threerings.crowd.data.Place; import com.threerings.crowd.data.PlaceConfig; import com.threerings.crowd.data.PlaceObject; import com.threerings.crowd.server.CrowdServer; @@ -59,14 +60,14 @@ public class LocationProvider * Requests that this client's body be moved to the specified location. * * @param caller the client object of the client that invoked this remotely callable method. - * @param placeId the object id of the place object to which the body should be moved. + * @param place the oid of the place to which the body should be moved. * @param listener the listener that will be informed of success or failure. */ - public void moveTo (ClientObject caller, int placeId, LocationService.MoveListener listener) + public void moveTo (ClientObject caller, int placeOid, LocationService.MoveListener listener) throws InvocationException { // do the move and send the response - listener.moveSucceeded(moveTo((BodyObject)caller, placeId)); + listener.moveSucceeded(moveTo((BodyObject)caller, placeOid)); } /** @@ -80,31 +81,32 @@ public class LocationProvider /** * Moves the specified body from whatever location they currently occupy to the location - * identified by the supplied place id. + * identified by the supplied place oid. * * @return the config object for the new location. * * @exception ServiceFaildException thrown if the move was not successful for some reason * (which will be communicated as an error code in the exception's message data). */ - public PlaceConfig moveTo (BodyObject source, int placeId) + public PlaceConfig moveTo (BodyObject source, int placeOid) throws InvocationException { int bodoid = source.getOid(); // make sure the place in question actually exists - PlaceManager pmgr = _plreg.getPlaceManager(placeId); + PlaceManager pmgr = _plreg.getPlaceManager(placeOid); if (pmgr == null) { Log.info("Requested to move to non-existent place [who=" + source.who() + - ", place=" + placeId + "]."); + ", placeOid=" + placeOid + "]."); throw new InvocationException(NO_SUCH_PLACE); } // if they're already in the location they're asking to move to, just give them the config // because we don't need to update anything in distributed object world - if (source.location == placeId) { + Place place = pmgr.getLocation(); + if (place.equals(source.location)) { Log.debug("Going along with client request to move to where they already are " + - "[source=" + source.who() + ", placeId=" + placeId + "]."); + "[source=" + source.who() + ", place=" + place + "]."); return pmgr.getConfig(); } @@ -127,11 +129,11 @@ public class LocationProvider } try { - PlaceObject place = pmgr.getPlaceObject(); + PlaceObject plobj = pmgr.getPlaceObject(); // the doubly nested try catch is to prevent failure if one or the other of the // transactions fails to start - place.startTransaction(); + plobj.startTransaction(); try { source.startTransaction(); try { @@ -142,16 +144,16 @@ public class LocationProvider pmgr.buildOccupantInfo(source); // set the body's new location - source.setLocation(place.getOid()); + source.setLocation(place); // add the body oid to the place object's occupant list - place.addToOccupants(bodoid); + plobj.addToOccupants(bodoid); } finally { source.commitTransaction(); } } finally { - place.commitTransaction(); + plobj.commitTransaction(); } } finally { @@ -168,17 +170,17 @@ public class LocationProvider */ public void leaveOccupiedPlace (BodyObject source) { - int oldloc = source.location; + Place oldloc = source.location; int bodoid = source.getOid(); // nothing to do if they weren't previously in some location - if (oldloc == -1) { + if (oldloc == null) { return; } // remove them from the occupant list try { - PlaceObject pold = (PlaceObject)_omgr.getObject(oldloc); + PlaceObject pold = (PlaceObject)_omgr.getObject(oldloc.placeOid); if (pold != null) { Integer key = Integer.valueOf(bodoid); pold.startTransaction(); @@ -194,16 +196,16 @@ public class LocationProvider } else { Log.info("Body's prior location no longer around? [boid=" + bodoid + - ", poid=" + oldloc + "]."); + ", place=" + oldloc + "]."); } } catch (ClassCastException cce) { Log.warning("Body claims to occupy non-PlaceObject!? [boid=" + bodoid + - ", poid=" + oldloc + ", error=" + cce + "]."); + ", place=" + oldloc + ", error=" + cce + "]."); } - // clear out their location oid - source.setLocation(-1); + // clear out their location + source.setLocation(null); } /** @@ -214,13 +216,13 @@ public class LocationProvider * or not they are cooperating. If they choose to ignore the forced move request, they will * remain in limbo, unable to do much of anything. */ - public void moveBody (BodyObject source, int placeId) + public void moveBody (BodyObject source, Place place) { // first remove them from their old place leaveOccupiedPlace(source); // then send a forced move notification - LocationSender.forcedMove(source, placeId); + LocationSender.forcedMove(source, place.placeOid); } /** The invocation manager with which we interoperate. */ diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index 00643d52c..7edf500e8 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -52,6 +52,7 @@ import com.threerings.presents.dobj.SetAdapter; import com.threerings.crowd.Log; import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.OccupantInfo; +import com.threerings.crowd.data.Place; import com.threerings.crowd.data.PlaceConfig; import com.threerings.crowd.data.PlaceObject; @@ -103,6 +104,14 @@ public class PlaceManager return _config; } + /** + * Returns a {@link Place} instance that identifies this place. + */ + public Place getLocation () + { + return new Place(_plobj.getOid()); + } + /** * Returns the place object managed by this place manager. */ diff --git a/src/java/com/threerings/crowd/server/PlaceRegistry.java b/src/java/com/threerings/crowd/server/PlaceRegistry.java index 5f24879fe..d4160a618 100644 --- a/src/java/com/threerings/crowd/server/PlaceRegistry.java +++ b/src/java/com/threerings/crowd/server/PlaceRegistry.java @@ -31,14 +31,14 @@ import com.threerings.presents.server.InvocationManager; import com.threerings.crowd.Log; import com.threerings.crowd.data.CrowdCodes; +import com.threerings.crowd.data.Place; import com.threerings.crowd.data.PlaceConfig; import com.threerings.crowd.data.PlaceObject; /** - * The place registry keeps track of all of the active places in the - * server. It should be used to create new places and it will take care of - * instantiating and initializing a place manager to manage newly created - * places. + * The place registry keeps track of all of the active places in the server. It should be used to + * create new places and it will take care of instantiating and initializing a place manager to + * manage newly created places. */ public class PlaceRegistry { @@ -48,13 +48,13 @@ public class PlaceRegistry public void invoke (PlaceManager plmgr); } - /** The location provider used by the place registry to provide - * location-related invocation services. */ + /** The location provider used by the place registry to provide location-related invocation + * services. */ public LocationProvider locprov; /** - * Creates and initializes the place registry; called by the server - * during its initialization phase. + * Creates and initializes the place registry. This is called by the server during its + * initialization phase. */ public PlaceRegistry (InvocationManager invmgr, RootDObjectManager omgr) { @@ -68,15 +68,12 @@ public class PlaceRegistry } /** - * By overriding this method, it is possible to customize the place - * registry to cause it to load the classes associated with a - * particular place via a custom class loader. That loader may enforce - * restricted privileges or obtain the classes from some special - * source. + * By overriding this method, it is possible to customize the place registry to cause it to + * load the classes associated with a particular place via a custom class loader. That loader + * may enforce restricted privileges or obtain the classes from some special source. * - * @return the class loader to use when instantiating the {@link - * PlaceManager} associated with the supplied {@link - * PlaceConfig}. This method must not return null. + * @return the class loader to use when instantiating the {@link PlaceManager} associated with + * the supplied {@link PlaceConfig}. This method must not return null. */ public ClassLoader getClassLoader (PlaceConfig config) { @@ -84,23 +81,22 @@ public class PlaceRegistry } /** - * Creates and registers a new place manager along with the place object to - * be managed. The registry takes care of tracking the creation of the - * object and informing the manager when it is created. + * Creates and registers a new place manager along with the place object to be managed. The + * registry takes care of tracking the creation of the object and informing the manager when it + * is created. * - * @param config the configuration object for the place to be created. The - * {@link PlaceManager} derived class that should be instantiated to manage - * the place will be determined from the config object. + * @param config the configuration object for the place to be created. The {@link PlaceManager} + * derived class that should be instantiated to manage the place will be determined from the + * config object. * - * @return a reference to the place manager, which will have been - * configured with its place object and started up (via a call to {@link - * PlaceManager#startup}. + * @return a reference to the place manager, which will have been configured with its place + * object and started up (via a call to {@link PlaceManager#startup}. * - * @exception InstantiationException thrown if an error occurs trying to - * instantiate and initialize the place manager. - * @exception InvocationException thrown if the place manager returns - * failure from the call to {@link PlaceManager#checkPermissions}. The - * error string returned by that call will be provided as in the exception. + * @exception InstantiationException thrown if an error occurs trying to instantiate and + * initialize the place manager. + * @exception InvocationException thrown if the place manager returns failure from the call to + * {@link PlaceManager#checkPermissions}. The error string returned by that call will be + * provided as in the exception. */ public PlaceManager createPlace (PlaceConfig config) throws InstantiationException, InvocationException @@ -109,12 +105,11 @@ public class PlaceRegistry } /** - * Don't use this method, see {@link #createPlace(PlaceConfig)}.. + * Don't use this method, see {@link #createPlace(PlaceConfig)}. * - * @param hook an optional pre-startup hook that allows a place manager to - * be configured prior to having {@link PlaceManager#startup} called. This - * mainly exists because it used to be possible to do such things. Try not - * to use this in new code. + * @param hook an optional pre-startup hook that allows a place manager to be configured prior + * to having {@link PlaceManager#startup} called. This mainly exists because it used to be + * possible to do such things. Try not to use this in new code. */ public PlaceManager createPlace (PlaceConfig config, PreStartupHook hook) throws InstantiationException, InvocationException @@ -124,8 +119,7 @@ public class PlaceRegistry try { // load up the manager class - Class pmgrClass = Class.forName( - config.getManagerClassName(), true, loader); + Class pmgrClass = Class.forName(config.getManagerClassName(), true, loader); // create a place manager for this place pmgr = (PlaceManager)pmgrClass.newInstance(); // let the pmgr know about us and its configuration @@ -137,12 +131,11 @@ public class PlaceRegistry "Error creating place manager [config=" + config + "]."); } - // give the manager an opportunity to abort the whole process - // if it fails any permissions checks + // give the manager an opportunity to abort the whole process if it fails any permissions + // checks String errmsg = pmgr.checkPermissions(); if (errmsg != null) { - // give the place manager a chance to clean up after its early - // initialization process + // give the place manager a chance to clean up after its early initialization process pmgr.permissionsFailed(); throw new InvocationException(errmsg); } @@ -159,11 +152,9 @@ public class PlaceRegistry if (hook != null) { hook.invoke(pmgr); } - pmgr.startup(plobj); } catch (Exception e) { - Log.warning("Error starting place manager [obj=" + plobj + - ", pmgr=" + pmgr + "]."); + Log.warning("Error starting place manager [obj=" + plobj + ", pmgr=" + pmgr + "]."); Log.logStackTrace(e); } @@ -171,8 +162,8 @@ public class PlaceRegistry } /** - * Returns the place manager associated with the specified place - * object id or null if no such place exists. + * Returns the place manager associated with the specified place object id or null if no such + * place exists. */ public PlaceManager getPlaceManager (int placeOid) { @@ -180,36 +171,29 @@ public class PlaceRegistry } /** - * Returns an enumeration of all of the registered place objects. This - * should only be accessed on the dobjmgr thread and shouldn't be kept - * around across event dispatches. + * Returns an enumeration of all of the registered place objects. This should only be accessed + * on the dobjmgr thread and shouldn't be kept around across event dispatches. */ public Iterator enumeratePlaces () { final Iterator itr = _pmgrs.values().iterator(); return new Iterator() { - public boolean hasNext () - { + public boolean hasNext (){ return itr.hasNext(); } - - public PlaceObject next () - { + public PlaceObject next () { PlaceManager plmgr = itr.next(); return (plmgr == null) ? null : plmgr.getPlaceObject(); } - - public void remove () - { + public void remove () { throw new UnsupportedOperationException(); } }; } /** - * Returns an enumeration of all of the registered place managers. - * This should only be accessed on the dobjmgr thread and shouldn't be - * kept around across event dispatches. + * Returns an enumeration of all of the registered place managers. This should only be + * accessed on the dobjmgr thread and shouldn't be kept around across event dispatches. */ public Iterator enumeratePlaceManagers () { @@ -224,12 +208,10 @@ public class PlaceRegistry int ploid = pmgr.getPlaceObject().getOid(); // remove it from the table if (_pmgrs.remove(ploid) == null) { - Log.warning("Requested to unmap unmapped place manager " + - "[pmgr=" + pmgr + "]."); + Log.warning("Requested to unmap unmapped place manager [pmgr=" + pmgr + "]."); // } else { -// Log.info("Unmapped place manager " + -// "[class=" + pmgr.getClass().getName() + +// Log.info("Unmapped place manager [class=" + pmgr.getClass().getName() + // ", ploid=" + ploid + "]."); } }