Widened, modified traversePortal() so that the entire portal being traversed is
kept around and passed to mapEnteringBody() so that in Whirled instead of having a portal map to a destination portal we can simply have the source portal contain the location in the destination scene at which the arriver is to be mapped. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@321 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -55,11 +55,10 @@ public class SpotProvider
|
||||
implements SpotCodes, InvocationProvider
|
||||
{
|
||||
/**
|
||||
* Creates a spot provider that can be registered with the invocation
|
||||
* manager to handle spot services.
|
||||
* Creates a spot provider that can be registered with the invocation manager to handle spot
|
||||
* services.
|
||||
*/
|
||||
public SpotProvider (RootDObjectManager omgr, PlaceRegistry plreg,
|
||||
SceneRegistry screg)
|
||||
public SpotProvider (RootDObjectManager omgr, PlaceRegistry plreg, SceneRegistry screg)
|
||||
{
|
||||
// we'll need these later
|
||||
_plreg = plreg;
|
||||
@@ -77,9 +76,9 @@ public class SpotProvider
|
||||
// le sanity check
|
||||
int cSceneId = getCallerSceneId(caller);
|
||||
if (cSceneId != sceneId) {
|
||||
Log.info("Ignoring stale traverse portal request " +
|
||||
"[caller=" + caller.who() + ", oSceneId=" + sceneId +
|
||||
", portalId=" + portalId + ", cSceneId=" + cSceneId + "].");
|
||||
Log.info("Ignoring stale traverse portal request [caller=" + caller.who() +
|
||||
", oSceneId=" + sceneId + ", portalId=" + portalId +
|
||||
", cSceneId=" + cSceneId + "].");
|
||||
InvocationMarshaller.setNoResponse(listener);
|
||||
return;
|
||||
}
|
||||
@@ -91,8 +90,7 @@ public class SpotProvider
|
||||
final SceneMoveListener flistener = listener;
|
||||
|
||||
// obtain the source scene
|
||||
final SpotSceneManager srcmgr = (SpotSceneManager)
|
||||
_screg.getSceneManager(sceneId);
|
||||
final SpotSceneManager srcmgr = (SpotSceneManager)_screg.getSceneManager(sceneId);
|
||||
if (srcmgr == null) {
|
||||
Log.warning("Traverse portal missing source scene " +
|
||||
"[user=" + fsource.who() + ", sceneId=" + sceneId +
|
||||
@@ -112,60 +110,52 @@ public class SpotProvider
|
||||
|
||||
// make sure this portal has valid info
|
||||
if (fdest == null || !fdest.isValid()) {
|
||||
Log.warning("Traverse portal with invalid portal " +
|
||||
"[user=" + fsource.who() + ", scene=" + srcmgr.where() +
|
||||
", pid=" + portalId + ", portal=" + fdest +
|
||||
", portals=" + StringUtil.toString(rss.getPortals()) +
|
||||
"].");
|
||||
Log.warning("Traverse portal with invalid portal [user=" + fsource.who() +
|
||||
", scene=" + srcmgr.where() + ", pid=" + portalId + ", portal=" + fdest +
|
||||
", portals=" + StringUtil.toString(rss.getPortals()) + "].");
|
||||
throw new InvocationException(NO_SUCH_PORTAL);
|
||||
}
|
||||
|
||||
// resolve their destination scene
|
||||
SceneRegistry.ResolutionListener rl =
|
||||
new SceneRegistry.ResolutionListener() {
|
||||
public void sceneWasResolved (SceneManager scmgr) {
|
||||
// make sure our caller is still around; under heavy
|
||||
// load, clients might end their session while the
|
||||
// scene is resolving
|
||||
if (!fsource.isActive()) {
|
||||
Log.info("Abandoning portal traversal, client gone " +
|
||||
"[who=" + fsource.who() +
|
||||
", dest=" + scmgr.where() + "].");
|
||||
InvocationMarshaller.setNoResponse(flistener);
|
||||
return;
|
||||
}
|
||||
|
||||
// let the source manager know that this guy is
|
||||
// departing via the specified portal
|
||||
srcmgr.willTraversePortal(fsource, fdest);
|
||||
|
||||
SpotSceneManager sscmgr = (SpotSceneManager)scmgr;
|
||||
finishTraversePortalRequest(
|
||||
fsource, sscmgr, fsceneVer, fdest, flistener);
|
||||
SceneRegistry.ResolutionListener rl = new SceneRegistry.ResolutionListener() {
|
||||
public void sceneWasResolved (SceneManager scmgr) {
|
||||
// make sure our caller is still around; under heavy load, clients might end their
|
||||
// session while the scene is resolving
|
||||
if (!fsource.isActive()) {
|
||||
Log.info("Abandoning portal traversal, client gone [who=" + fsource.who() +
|
||||
", dest=" + scmgr.where() + "].");
|
||||
InvocationMarshaller.setNoResponse(flistener);
|
||||
return;
|
||||
}
|
||||
|
||||
public void sceneFailedToResolve (
|
||||
int rsceneId, Exception reason) {
|
||||
Log.warning("Unable to resolve target scene " +
|
||||
"[sceneId=" + rsceneId +
|
||||
", reason=" + reason + "].");
|
||||
// pretend like the scene doesn't exist to the client
|
||||
flistener.requestFailed(NO_SUCH_PLACE);
|
||||
}
|
||||
};
|
||||
// let the source manager know that this guy is departing via the specified portal
|
||||
srcmgr.willTraversePortal(fsource, fdest);
|
||||
|
||||
SpotSceneManager sscmgr = (SpotSceneManager)scmgr;
|
||||
finishTraversePortalRequest(fsource, sscmgr, fsceneVer, fdest, flistener);
|
||||
}
|
||||
|
||||
public void sceneFailedToResolve (
|
||||
int rsceneId, Exception reason) {
|
||||
Log.warning("Unable to resolve target scene [sceneId=" + rsceneId +
|
||||
", reason=" + reason + "].");
|
||||
// pretend like the scene doesn't exist to the client
|
||||
flistener.requestFailed(NO_SUCH_PLACE);
|
||||
}
|
||||
};
|
||||
_screg.resolveScene(fdest.targetSceneId, rl);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called after the scene to which we are moving is guaranteed
|
||||
* to have been loaded into the server.
|
||||
* This is called after the scene to which we are moving is guaranteed to have been loaded into
|
||||
* the server.
|
||||
*/
|
||||
protected void finishTraversePortalRequest (
|
||||
BodyObject source, SpotSceneManager destmgr, int sceneVer,
|
||||
Portal dest, SceneMoveListener listener)
|
||||
BodyObject source, SpotSceneManager destmgr, int sceneVer, Portal dest,
|
||||
SceneMoveListener listener)
|
||||
{
|
||||
// let the destination scene manager know that we're coming in
|
||||
destmgr.mapEnteringBody(source, dest.targetPortalId);
|
||||
destmgr.mapEnteringBody(source, dest);
|
||||
|
||||
try {
|
||||
// move to the place object associated with this scene
|
||||
@@ -189,19 +179,16 @@ public class SpotProvider
|
||||
BodyObject source = (BodyObject)caller;
|
||||
int cSceneId = getCallerSceneId(caller);
|
||||
if (cSceneId != sceneId) {
|
||||
Log.info("Rejecting changeLocation for invalid scene " +
|
||||
"[user=" + source.who() + ", insid=" + cSceneId +
|
||||
", wantsid=" + sceneId + ", loc=" + loc + "].");
|
||||
Log.info("Rejecting changeLocation for invalid scene [user=" + source.who() +
|
||||
", insid=" + cSceneId + ", wantsid=" + sceneId + ", loc=" + loc + "].");
|
||||
throw new InvocationException(INVALID_LOCATION);
|
||||
}
|
||||
|
||||
// look up the scene manager for the specified scene
|
||||
SpotSceneManager smgr = (SpotSceneManager)
|
||||
_screg.getSceneManager(sceneId);
|
||||
SpotSceneManager smgr = (SpotSceneManager)_screg.getSceneManager(sceneId);
|
||||
if (smgr == null) {
|
||||
Log.warning("User requested to change location from " +
|
||||
"non-existent scene [user=" + source.who() +
|
||||
", sceneId=" + sceneId + ", loc=" + loc +"].");
|
||||
Log.warning("User requested to change location from non-existent scene " +
|
||||
"[user=" + source.who() + ", sceneId=" + sceneId + ", loc=" + loc +"].");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
@@ -223,12 +210,11 @@ public class SpotProvider
|
||||
BodyObject source = (BodyObject)caller;
|
||||
|
||||
// look up the scene manager for the specified scene
|
||||
SpotSceneManager smgr = (SpotSceneManager)
|
||||
_screg.getSceneManager(sceneId);
|
||||
SpotSceneManager smgr = (SpotSceneManager)_screg.getSceneManager(sceneId);
|
||||
if (smgr == null) {
|
||||
Log.warning("User requested to join cluster from " +
|
||||
"non-existent scene [user=" + source.who() +
|
||||
", sceneId=" + sceneId + ", foid=" + friendOid +"].");
|
||||
Log.warning("User requested to join cluster from non-existent scene " +
|
||||
"[user=" + source.who() + ", sceneId=" + sceneId +
|
||||
", foid=" + friendOid +"].");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
@@ -249,57 +235,50 @@ public class SpotProvider
|
||||
BodyObject source = (BodyObject)caller;
|
||||
String errmsg = source.checkAccess(ChatCodes.CHAT_ACCESS, null);
|
||||
if (errmsg != null) {
|
||||
SpeakProvider.sendFeedback(source,
|
||||
MessageManager.GLOBAL_BUNDLE, errmsg);
|
||||
return;
|
||||
SpeakProvider.sendFeedback(source, MessageManager.GLOBAL_BUNDLE, errmsg);
|
||||
} else {
|
||||
sendClusterChatMessage(getCallerSceneId(caller), source.getOid(),
|
||||
source.getVisibleName(), null, message, mode);
|
||||
}
|
||||
|
||||
sendClusterChatMessage(getCallerSceneId(caller), source.getOid(),
|
||||
source.getVisibleName(), null, message, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a cluster chat notification to the specified location in the
|
||||
* specified place object originating with the specified speaker (the
|
||||
* speaker can be a server entity that wishes to fake a "speak"
|
||||
* message, in which case the bundle argument should be non-null and
|
||||
* should contain the id of the bundle to be used to translate the
|
||||
* message text) and with the supplied message content.
|
||||
* Sends a cluster chat notification to the specified location in the specified place object
|
||||
* originating with the specified speaker (the speaker can be a server entity that wishes to
|
||||
* fake a "speak" message, in which case the bundle argument should be non-null and should
|
||||
* contain the id of the bundle to be used to translate the message text) and with the supplied
|
||||
* message content.
|
||||
*
|
||||
* @param sceneId the scene id in which to deliver the chat message.
|
||||
* @param speakerOid the body object id of the speaker (used to verify
|
||||
* that they are in the cluster in question).
|
||||
* @param speaker the username of the user that generated the message
|
||||
* (or some special speaker name for server messages).
|
||||
* @param bundle the bundle identifier that will be used by the client
|
||||
* to translate the message text (or null if the message originated
|
||||
* from a real live human who wrote it in their native tongue).
|
||||
* @param speakerOid the body object id of the speaker (used to verify that they are in the
|
||||
* cluster in question).
|
||||
* @param speaker the username of the user that generated the message (or some special speaker
|
||||
* name for server messages).
|
||||
* @param bundle the bundle identifier that will be used by the client to translate the message
|
||||
* text (or null if the message originated from a real live human who wrote it in their native
|
||||
* tongue).
|
||||
* @param message the text of the chat message.
|
||||
*/
|
||||
public void sendClusterChatMessage (
|
||||
int sceneId, int speakerOid, Name speaker,
|
||||
String bundle, String message, byte mode)
|
||||
public void sendClusterChatMessage (int sceneId, int speakerOid, Name speaker,
|
||||
String bundle, String message, byte mode)
|
||||
{
|
||||
// look up the scene manager for the specified scene
|
||||
SpotSceneManager smgr = (SpotSceneManager)
|
||||
_screg.getSceneManager(sceneId);
|
||||
SpotSceneManager smgr = (SpotSceneManager)_screg.getSceneManager(sceneId);
|
||||
if (smgr == null) {
|
||||
Log.warning("User requested cluster chat in non-existent scene " +
|
||||
"[user=" + speaker + ", sceneId=" + sceneId +
|
||||
", message=" + message + "].");
|
||||
Log.warning("User requested cluster chat in non-existent scene [user=" + speaker +
|
||||
", sceneId=" + sceneId + ", message=" + message + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// pass this request on to the spot scene manager
|
||||
smgr.handleClusterSpeakRequest(
|
||||
speakerOid, speaker, bundle, message, mode);
|
||||
smgr.handleClusterSpeakRequest(speakerOid, speaker, bundle, message, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the scene id occupied by the supplied caller.
|
||||
*
|
||||
* @exception InvocationException thrown if the caller does not
|
||||
* implement {@link ScenedBodyObject}.
|
||||
* @exception InvocationException thrown if the caller does not implement {@link
|
||||
* ScenedBodyObject}.
|
||||
*/
|
||||
protected static int getCallerSceneId (ClientObject caller)
|
||||
throws InvocationException
|
||||
@@ -307,8 +286,7 @@ public class SpotProvider
|
||||
if (caller instanceof ScenedBodyObject) {
|
||||
return ((ScenedBodyObject)caller).getSceneId();
|
||||
} else {
|
||||
Log.warning("Can't get scene from non-scened caller " +
|
||||
caller.who() + ".");
|
||||
Log.warning("Can't get scene from non-scened caller " + caller.who() + ".");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
|
||||
package com.threerings.whirled.spot.server;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.samskivert.util.IntIntMap;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
@@ -50,9 +50,8 @@ import com.threerings.whirled.spot.data.SpotScene;
|
||||
import com.threerings.whirled.spot.data.SpotSceneObject;
|
||||
|
||||
/**
|
||||
* Handles the movement of bodies between locations in the scene and
|
||||
* creates the necessary distributed objects to allow bodies in clusters
|
||||
* to chat with one another.
|
||||
* Handles the movement of bodies between locations in the scene and creates the necessary
|
||||
* distributed objects to allow bodies in clusters to chat with one another.
|
||||
*/
|
||||
public class SpotSceneManager extends SceneManager
|
||||
implements SpotCodes
|
||||
@@ -62,8 +61,7 @@ public class SpotSceneManager extends SceneManager
|
||||
*/
|
||||
public static void moveBodyToDefaultPortal (BodyObject body)
|
||||
{
|
||||
SpotSceneManager mgr = (SpotSceneManager)
|
||||
CrowdServer.plreg.getPlaceManager(body.location);
|
||||
SpotSceneManager mgr = (SpotSceneManager)CrowdServer.plreg.getPlaceManager(body.location);
|
||||
if (mgr != null) {
|
||||
SpotScene scene = (SpotScene)mgr.getScene();
|
||||
if (scene == null) {
|
||||
@@ -84,24 +82,20 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a starting location for an entering body. This will happen
|
||||
* before the body is made to "occupy" the scene (defined by their
|
||||
* having an occupant info record). So when they do finally occupy the
|
||||
* scene, the client will know where to render them.
|
||||
* Assigns a starting location for an entering body. This will happen before the body is made
|
||||
* to "occupy" the scene (defined by their having an occupant info record). So when they do
|
||||
* finally occupy the scene, the client will know where to render them.
|
||||
*/
|
||||
public void mapEnteringBody (BodyObject body, int portalId)
|
||||
public void mapEnteringBody (BodyObject body, Portal from)
|
||||
{
|
||||
// small optimization: don't save portalId -1, because it simply means
|
||||
// "use the default entrance" and retrieving an unset value will
|
||||
// return -1 anyway
|
||||
if (portalId != -1) {
|
||||
_enterers.put(body.getOid(), portalId);
|
||||
// don't save a null from portal, because it simply means "use the default entrance"
|
||||
if (from != null) {
|
||||
_enterers.put(body.getOid(), from);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if a body failed to enter our scene after we assigned them
|
||||
* an entering position.
|
||||
* Called if a body failed to enter our scene after we assigned them an entering position.
|
||||
*/
|
||||
public void clearEnteringBody (BodyObject body)
|
||||
{
|
||||
@@ -109,10 +103,9 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a user requests to traverse a portal from this
|
||||
* scene to another scene. The manager may return an error code string
|
||||
* that will be reported back to the caller explaining the failure or
|
||||
* <code>null</code> indicating that it is OK for the caller to
|
||||
* This is called when a user requests to traverse a portal from this scene to another scene.
|
||||
* The manager may return an error code string that will be reported back to the caller
|
||||
* explaining the failure or <code>null</code> indicating that it is OK for the caller to
|
||||
* traverse the portal.
|
||||
*/
|
||||
public String mayTraversePortal (BodyObject body, Portal portal)
|
||||
@@ -121,11 +114,10 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called to let this scene manager know that the user is
|
||||
* about to traverse the specified portal. The default implementation
|
||||
* relocates the user to the location associated with the portal. It
|
||||
* is still possible that the traversal will fail, so don't do
|
||||
* anything too crazy.
|
||||
* This is called to let this scene manager know that the user is about to traverse the
|
||||
* specified portal. The default implementation relocates the user to the location associated
|
||||
* with the portal. It is still possible that the traversal will fail, so don't do anything too
|
||||
* crazy.
|
||||
*/
|
||||
public void willTraversePortal (BodyObject body, Portal portal)
|
||||
{
|
||||
@@ -135,10 +127,9 @@ public class SpotSceneManager extends SceneManager
|
||||
// documentation inherited
|
||||
protected void didStartup ()
|
||||
{
|
||||
// get a casted reference to our place object (we need to do this
|
||||
// before calling super.didStartup() because that will call
|
||||
// sceneManagerDidResolve() which may start letting people into
|
||||
// the scene)
|
||||
// get a casted reference to our place object (we need to do this before calling
|
||||
// super.didStartup() because that will call sceneManagerDidResolve() which may start
|
||||
// letting people into the scene)
|
||||
_ssobj = (SpotSceneObject)_plobj;
|
||||
|
||||
super.didStartup();
|
||||
@@ -165,17 +156,16 @@ public class SpotSceneManager extends SceneManager
|
||||
removeFromCluster(bodyOid);
|
||||
|
||||
// let's make damned sure they're not in any cluster
|
||||
Iterator cliter = _clusters.values().iterator();
|
||||
Iterator<ClusterRecord> cliter = _clusters.values().iterator();
|
||||
while (cliter.hasNext()) {
|
||||
ClusterRecord clrec = (ClusterRecord)cliter.next();
|
||||
ClusterRecord clrec = cliter.next();
|
||||
if (clrec.containsKey(bodyOid)) {
|
||||
Log.info("Pruning departed body from cluster [boid=" + bodyOid +
|
||||
", cluster=" + clrec + "].");
|
||||
clrec.removeBody(bodyOid);
|
||||
if (clrec.size() == 0) {
|
||||
// If we just removed the last body, destroy the cluster,
|
||||
// need to use the iterator's removal so we don't
|
||||
// hose ourselves.
|
||||
// if we just removed the last body, destroy the cluster, need to use the
|
||||
// iterator's removal so we don't hose ourselves
|
||||
clrec.destroy(false);
|
||||
cliter.remove();
|
||||
}
|
||||
@@ -188,25 +178,23 @@ public class SpotSceneManager extends SceneManager
|
||||
{
|
||||
super.insertOccupantInfo(info, body);
|
||||
|
||||
// we don't actually populate their occupant info, but instead assign
|
||||
// them their starting location in the scene
|
||||
// we don't actually populate their occupant info, but instead assign them their starting
|
||||
// location in the scene
|
||||
assignStartingLocation(body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Give our new body a starting location.
|
||||
* @param body The new body entering the scene.
|
||||
*/
|
||||
protected void assignStartingLocation (BodyObject body)
|
||||
{
|
||||
int portalId = _enterers.remove(body.getOid());
|
||||
Portal from = _enterers.remove(body.getOid());
|
||||
Portal entry;
|
||||
if (portalId != -1) {
|
||||
entry = _sscene.getPortal(portalId);
|
||||
if (from != null && from.portalId != -1) {
|
||||
entry = _sscene.getPortal(from.portalId);
|
||||
if (entry == null) {
|
||||
Log.warning("Body mapped at invalid portal [where=" + where() +
|
||||
", who=" + body.who() +
|
||||
", portalId=" + portalId + "].");
|
||||
", who=" + body.who() + ", from=" + from + "].");
|
||||
entry = _sscene.getDefaultEntrance();
|
||||
}
|
||||
} else {
|
||||
@@ -216,40 +204,37 @@ public class SpotSceneManager extends SceneManager
|
||||
// Log.debug("Positioning entering body [who=" + body.who() +
|
||||
// ", where=" + entry.getOppLocation() + "].");
|
||||
|
||||
// create a scene location for them located on the entrance portal
|
||||
// but facing the opposite direction
|
||||
// create a scene location for them located on the entrance portal but facing the opposite
|
||||
// direction
|
||||
_ssobj.addToOccupantLocs(computeEnteringLocation(body, entry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the supplied body is entering our scene via the
|
||||
* specified portal. The default location is the one associated with
|
||||
* the portal, but derived classes may wish to adjust this.
|
||||
* Called when the supplied body is entering our scene via the specified portal. The default
|
||||
* location is the one associated with the portal, but derived classes may wish to adjust this.
|
||||
*/
|
||||
protected SceneLocation computeEnteringLocation (
|
||||
BodyObject body, Portal entry)
|
||||
protected SceneLocation computeEnteringLocation (BodyObject body, Portal entry)
|
||||
{
|
||||
return new SceneLocation(entry.getOppLocation(), body.getOid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link SpotProvider} when we receive a request by a
|
||||
* user to occupy a particular location.
|
||||
* Called by the {@link SpotProvider} when we receive a request by a user to occupy a
|
||||
* particular location.
|
||||
*
|
||||
* @param source the body to be moved.
|
||||
* @param loc the location to which to move the body.
|
||||
*
|
||||
* @exception InvocationException thrown with a reason code explaining
|
||||
* the failure if there is a problem processing the request.
|
||||
* @exception InvocationException thrown with a reason code explaining the failure if there is
|
||||
* a problem processing the request.
|
||||
*/
|
||||
protected void handleChangeLoc (BodyObject source, Location loc)
|
||||
throws InvocationException
|
||||
{
|
||||
// make sure they are in our scene
|
||||
if (!_ssobj.occupants.contains(source.getOid())) {
|
||||
Log.warning("Refusing change loc from non-scene occupant " +
|
||||
"[where=" + where() + ", who=" + source.who() +
|
||||
", loc=" + loc + "].");
|
||||
Log.warning("Refusing change loc from non-scene occupant [where=" + where() +
|
||||
", who=" + source.who() + ", loc=" + loc + "].");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
@@ -258,9 +243,8 @@ public class SpotSceneManager extends SceneManager
|
||||
throw new InvocationException(INVALID_LOCATION);
|
||||
}
|
||||
|
||||
// update the user's location information in the scene which will
|
||||
// indicate to the client that their avatar should be moved from
|
||||
// its current position to their new position
|
||||
// update the user's location information in the scene which will indicate to the client
|
||||
// that their avatar should be moved from its current position to their new position
|
||||
updateLocation(source, loc);
|
||||
|
||||
// remove them from any cluster as they've departed
|
||||
@@ -268,10 +252,9 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes can override this method and validate that the
|
||||
* specified body can stand in the requested location. The default
|
||||
* implementation returns <code>true</code> in all circumstances;
|
||||
* stand where ye may!
|
||||
* Derived classes can override this method and validate that the specified body can stand in
|
||||
* the requested location. The default implementation returns <code>true</code> in all
|
||||
* circumstances; stand where ye may!
|
||||
*/
|
||||
protected boolean validateLocation (BodyObject source, Location loc)
|
||||
{
|
||||
@@ -286,9 +269,8 @@ public class SpotSceneManager extends SceneManager
|
||||
SceneLocation sloc = new SceneLocation(loc, source.getOid());
|
||||
if (!_ssobj.occupantLocs.contains(sloc)) {
|
||||
// complain if they don't already have a location configured
|
||||
Log.warning("Changing loc for occupant without previous loc " +
|
||||
"[where=" + where() + ", who=" + source.who() +
|
||||
", nloc=" + loc + "].");
|
||||
Log.warning("Changing loc for occupant without previous loc [where=" + where() +
|
||||
", who=" + source.who() + ", nloc=" + loc + "].");
|
||||
Thread.dumpStack();
|
||||
_ssobj.addToOccupantLocs(sloc);
|
||||
} else {
|
||||
@@ -297,22 +279,21 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link SpotProvider} when we receive a request by a
|
||||
* user to join a particular cluster.
|
||||
* Called by the {@link SpotProvider} when we receive a request by a user to join a particular
|
||||
* cluster.
|
||||
*
|
||||
* @param joiner the body to be moved.
|
||||
* @param targetOid the bodyOid of another user or the oid of an
|
||||
* existing cluster; the moving user will be made to join the other
|
||||
* user's cluster.
|
||||
* @param targetOid the bodyOid of another user or the oid of an existing cluster; the moving
|
||||
* user will be made to join the other user's cluster.
|
||||
*
|
||||
* @exception InvocationException thrown with a reason code explaining
|
||||
* the failure if there is a problem processing the request.
|
||||
* @exception InvocationException thrown with a reason code explaining the failure if there is
|
||||
* a problem processing the request.
|
||||
*/
|
||||
protected void handleJoinCluster (BodyObject joiner, int targetOid)
|
||||
throws InvocationException
|
||||
{
|
||||
// if the cluster already exists, add this user and be done
|
||||
ClusterRecord clrec = (ClusterRecord)_clusters.get(targetOid);
|
||||
ClusterRecord clrec = _clusters.get(targetOid);
|
||||
if (clrec != null) {
|
||||
clrec.addBody(joiner);
|
||||
return;
|
||||
@@ -321,8 +302,7 @@ public class SpotSceneManager extends SceneManager
|
||||
// otherwise see if they sent us the user's oid
|
||||
DObject tobj = CrowdServer.omgr.getObject(targetOid);
|
||||
if (!(tobj instanceof BodyObject)) {
|
||||
Log.info("Can't join cluster, missing target " +
|
||||
"[creator=" + joiner.who() +
|
||||
Log.info("Can't join cluster, missing target [creator=" + joiner.who() +
|
||||
", targetOid=" + targetOid + "].");
|
||||
throw new InvocationException(NO_SUCH_CLUSTER);
|
||||
}
|
||||
@@ -330,9 +310,8 @@ public class SpotSceneManager extends SceneManager
|
||||
// make sure we're in the same scene as said user
|
||||
BodyObject friend = (BodyObject)tobj;
|
||||
if (friend.location != joiner.location) {
|
||||
Log.info("Refusing cluster join from non-proximate user " +
|
||||
"[joiner=" + joiner.who() + ", jloc=" + joiner.location +
|
||||
", target=" + friend.who() +
|
||||
Log.info("Refusing cluster join from non-proximate user [joiner=" + joiner.who() +
|
||||
", jloc=" + joiner.location + ", target=" + friend.who() +
|
||||
", tloc=" + friend.location + "].");
|
||||
throw new InvocationException(NO_SUCH_CLUSTER);
|
||||
}
|
||||
@@ -344,21 +323,18 @@ public class SpotSceneManager extends SceneManager
|
||||
return;
|
||||
}
|
||||
|
||||
// confirm that they can start a cluster with this unsuspecting
|
||||
// other person
|
||||
// confirm that they can start a cluster with this unsuspecting other person
|
||||
checkCanCluster(joiner, friend);
|
||||
|
||||
// otherwise we create a new cluster and add our charter members!
|
||||
// Log.debug("Creating cluster [starter=" + joiner.who() +
|
||||
// ", target=" + friend.who() + "].");
|
||||
// Log.debug("Creating cluster [starter=" + joiner.who() + ", tgt=" + friend.who() + "].");
|
||||
clrec = createClusterRecord();
|
||||
clrec.addBody(friend);
|
||||
clrec.addBody(joiner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the cluster record instance that we'll use to manage our
|
||||
* cluster.
|
||||
* Creates the cluster record instance that we'll use to manage our cluster.
|
||||
*/
|
||||
protected ClusterRecord createClusterRecord ()
|
||||
{
|
||||
@@ -366,10 +342,9 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives derived classes an opportunity to veto a user's attempt to
|
||||
* start a cluster with another user. If the attempt should be vetoed,
|
||||
* this method should throw an {@link InvocationException} indicating
|
||||
* the reason for veto.
|
||||
* Gives derived classes an opportunity to veto a user's attempt to start a cluster with
|
||||
* another user. If the attempt should be vetoed, this method should throw an {@link
|
||||
* InvocationException} indicating the reason for veto.
|
||||
*/
|
||||
protected void checkCanCluster (BodyObject initiator, BodyObject target)
|
||||
throws InvocationException
|
||||
@@ -397,33 +372,27 @@ public class SpotSceneManager extends SceneManager
|
||||
*/
|
||||
protected ClusterRecord getCluster (int bodyOid)
|
||||
{
|
||||
ClusteredBodyObject bobj = (ClusteredBodyObject)
|
||||
CrowdServer.omgr.getObject(bodyOid);
|
||||
return (bobj == null) ? null :
|
||||
(ClusterRecord)_clusters.get(bobj.getClusterOid());
|
||||
ClusteredBodyObject bobj = (ClusteredBodyObject)CrowdServer.omgr.getObject(bodyOid);
|
||||
return (bobj == null) ? null : _clusters.get(bobj.getClusterOid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link SpotProvider} when we receive a cluster speak
|
||||
* request.
|
||||
* Called by the {@link SpotProvider} when we receive a cluster speak request.
|
||||
*/
|
||||
protected void handleClusterSpeakRequest (
|
||||
int sourceOid, Name source, String bundle, String message, byte mode)
|
||||
protected void handleClusterSpeakRequest (int sourceOid, Name source, String bundle,
|
||||
String message, byte mode)
|
||||
{
|
||||
ClusterRecord clrec = getCluster(sourceOid);
|
||||
if (clrec == null) {
|
||||
Log.warning("Non-clustered user requested cluster speak " +
|
||||
"[where=" + where() + ", chatter=" + source +
|
||||
" (" + sourceOid + "), msg=" + message + "].");
|
||||
Log.warning("Non-clustered user requested cluster speak [where=" + where() +
|
||||
", chatter=" + source + " (" + sourceOid + "), msg=" + message + "].");
|
||||
} else {
|
||||
SpeakProvider.sendSpeak(clrec.getClusterObject(),
|
||||
source, bundle, message, mode);
|
||||
SpeakProvider.sendSpeak(clrec.getClusterObject(), source, bundle, message, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location of the specified body or null if they have no
|
||||
* location in this scene.
|
||||
* Returns the location of the specified body or null if they have no location in this scene.
|
||||
*/
|
||||
protected SceneLocation locationForBody (int bodyOid)
|
||||
{
|
||||
@@ -431,8 +400,7 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the specified cluster can be expanded to include
|
||||
* another body.
|
||||
* Verifies that the specified cluster can be expanded to include another body.
|
||||
*/
|
||||
protected boolean canAddBody (ClusterRecord clrec, BodyObject body)
|
||||
{
|
||||
@@ -440,26 +408,23 @@ public class SpotSceneManager extends SceneManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user is added to a cluster. The scene manager
|
||||
* implementation should take this opportunity to rearrange everyone
|
||||
* in the cluster appropriately for the new size.
|
||||
* Called when a user is added to a cluster. The scene manager implementation should take this
|
||||
* opportunity to rearrange everyone in the cluster appropriately for the new size.
|
||||
*/
|
||||
protected void bodyAdded (ClusterRecord clrec, BodyObject body)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user is removed from a cluster. The scene manager
|
||||
* implementation should take this opportunity to rearrange everyone
|
||||
* in the cluster appropriately for the new size.
|
||||
* Called when a user is removed from a cluster. The scene manager implementation should take
|
||||
* this opportunity to rearrange everyone in the cluster appropriately for the new size.
|
||||
*/
|
||||
protected void bodyRemoved (ClusterRecord clrec, BodyObject body)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to manage clusters which are groups of users that can chat to
|
||||
* one another.
|
||||
* Used to manage clusters which are groups of users that can chat to one another.
|
||||
*/
|
||||
protected class ClusterRecord extends HashIntMap
|
||||
{
|
||||
@@ -485,9 +450,8 @@ public class SpotSceneManager extends SceneManager
|
||||
throws InvocationException
|
||||
{
|
||||
if (!(body instanceof ClusteredBodyObject)) {
|
||||
Log.warning("Refusing to add non-clustered body to cluster " +
|
||||
"[cloid=" + _clobj.getOid() +
|
||||
", size=" + size() + ", who=" + body.who() + "].");
|
||||
Log.warning("Refusing to add non-clustered body to cluster [cloid=" +
|
||||
_clobj.getOid() + ", size=" + size() + ", who=" + body.who() + "].");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
@@ -511,10 +475,8 @@ public class SpotSceneManager extends SceneManager
|
||||
body.startTransaction();
|
||||
try {
|
||||
bodyAdded(this, body); // do the hokey pokey
|
||||
|
||||
if (_clobj != null) {
|
||||
((ClusteredBodyObject)body).setClusterOid(
|
||||
_clobj.getOid());
|
||||
((ClusteredBodyObject)body).setClusterOid(_clobj.getOid());
|
||||
_clobj.addToOccupants(body.getOid());
|
||||
_ssobj.updateClusters(_cluster);
|
||||
}
|
||||
@@ -534,9 +496,8 @@ public class SpotSceneManager extends SceneManager
|
||||
{
|
||||
BodyObject body = (BodyObject)remove(bodyOid);
|
||||
if (body == null) {
|
||||
Log.warning("Requested to remove unknown body from cluster " +
|
||||
"[cloid=" + _clobj.getOid() +
|
||||
", size=" + size() + ", who=" + bodyOid + "].");
|
||||
Log.warning("Requested to remove unknown body from cluster [cloid=" +
|
||||
_clobj.getOid() + ", size=" + size() + ", who=" + bodyOid + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -548,7 +509,6 @@ public class SpotSceneManager extends SceneManager
|
||||
try {
|
||||
((ClusteredBodyObject)body).setClusterOid(-1);
|
||||
bodyRemoved(this, body); // do the hokey pokey
|
||||
|
||||
if (_clobj != null) {
|
||||
_clobj.removeFromOccupants(bodyOid);
|
||||
_ssobj.updateClusters(_cluster);
|
||||
@@ -557,6 +517,7 @@ public class SpotSceneManager extends SceneManager
|
||||
} finally {
|
||||
_ssobj.commitTransaction();
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (body.isActive()) {
|
||||
body.commitTransaction();
|
||||
@@ -584,12 +545,10 @@ public class SpotSceneManager extends SceneManager
|
||||
|
||||
protected void destroy (boolean doRemoval)
|
||||
{
|
||||
// Log.debug("Cluster empty, going away " +
|
||||
// "[cloid=" + _clobj.getOid() + "].");
|
||||
// Log.debug("Cluster empty, going away [cloid=" + _clobj.getOid() + "].");
|
||||
_ssobj.removeFromClusters(_cluster.getKey());
|
||||
|
||||
// If we've also been requested to remove ourself from the clusters
|
||||
// list, do that.
|
||||
// if we've also been requested to remove ourself from the clusters list, do that
|
||||
if (doRemoval) {
|
||||
_clusters.remove(_clobj.getOid());
|
||||
}
|
||||
@@ -607,8 +566,8 @@ public class SpotSceneManager extends SceneManager
|
||||
protected SpotScene _sscene;
|
||||
|
||||
/** Records with information on all clusters in this scene. */
|
||||
protected HashIntMap _clusters = new HashIntMap();
|
||||
protected HashIntMap<ClusterRecord> _clusters = new HashIntMap<ClusterRecord>();
|
||||
|
||||
/** A mapping of entering bodies to portal ids. */
|
||||
protected IntIntMap _enterers = new IntIntMap();
|
||||
protected HashMap<Integer,Portal> _enterers = new HashMap<Integer,Portal>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user