Whirled lives in Vilya.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4210 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,63 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder class that contains a reference to the log object used by
|
|
||||||
* the Whirled services.
|
|
||||||
*/
|
|
||||||
public class Log
|
|
||||||
{
|
|
||||||
public static com.samskivert.util.Log log =
|
|
||||||
new com.samskivert.util.Log("whirled");
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static boolean debug ()
|
|
||||||
{
|
|
||||||
return (com.samskivert.util.Log.getLevel() ==
|
|
||||||
com.samskivert.util.Log.DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void debug (String message)
|
|
||||||
{
|
|
||||||
log.debug(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void info (String message)
|
|
||||||
{
|
|
||||||
log.info(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void warning (String message)
|
|
||||||
{
|
|
||||||
log.warning(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void logStackTrace (Throwable t)
|
|
||||||
{
|
|
||||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.dobj.MessageEvent;
|
|
||||||
import com.threerings.presents.dobj.MessageListener;
|
|
||||||
|
|
||||||
import com.threerings.crowd.client.PlaceController;
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.crowd.data.PlaceObject;
|
|
||||||
import com.threerings.crowd.util.CrowdContext;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.SceneCodes;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.util.WhirledContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base scene controller class. It is expected that users of the
|
|
||||||
* Whirled services will extend this controller class when creating
|
|
||||||
* specialized controllers for their scenes.
|
|
||||||
*/
|
|
||||||
public abstract class SceneController extends PlaceController
|
|
||||||
{
|
|
||||||
// documentation inherited
|
|
||||||
public void init (CrowdContext ctx, PlaceConfig config)
|
|
||||||
{
|
|
||||||
super.init(ctx, config);
|
|
||||||
_wctx = (WhirledContext)ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void willEnterPlace (PlaceObject plobj)
|
|
||||||
{
|
|
||||||
super.willEnterPlace(plobj);
|
|
||||||
plobj.addListener(_updateListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void didLeavePlace (PlaceObject plobj)
|
|
||||||
{
|
|
||||||
super.didLeavePlace(plobj);
|
|
||||||
plobj.removeListener(_updateListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called if a scene update is recorded while we
|
|
||||||
* currently occupy a scene. The default implementation will update
|
|
||||||
* our local scene and scene model, but derived classes will likely
|
|
||||||
* want to ensure that the update is properly displayed.
|
|
||||||
*/
|
|
||||||
protected void sceneUpdated (SceneUpdate update)
|
|
||||||
{
|
|
||||||
// apply the update to the scene
|
|
||||||
_wctx.getSceneDirector().getScene().updateReceived(update);
|
|
||||||
|
|
||||||
// we don't persistify these updates in this circumstance, but
|
|
||||||
// next time we come to this scene we'll redownload the update and
|
|
||||||
// apply it to the repository; as the updates are meant to be very
|
|
||||||
// small, this shouldn't be horribly less efficient
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used to listen for scene updates. */
|
|
||||||
protected MessageListener _updateListener = new MessageListener() {
|
|
||||||
public void messageReceived (MessageEvent event) {
|
|
||||||
if (event.getName().equals(SceneCodes.SCENE_UPDATE)) {
|
|
||||||
sceneUpdated((SceneUpdate)event.getArgs()[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected WhirledContext _wctx;
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.InvocationDecoder;
|
|
||||||
import com.threerings.whirled.client.SceneReceiver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches calls to a {@link SceneReceiver} instance.
|
|
||||||
*/
|
|
||||||
public class SceneDecoder extends InvocationDecoder
|
|
||||||
{
|
|
||||||
/** The generated hash code used to identify this receiver class. */
|
|
||||||
public static final String RECEIVER_CODE = "c4d0cf66b81a6e83d119b2d607725651";
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link SceneReceiver#forcedMove}
|
|
||||||
* notifications. */
|
|
||||||
public static final int FORCED_MOVE = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a decoder that may be registered to dispatch invocation
|
|
||||||
* service notifications to the specified receiver.
|
|
||||||
*/
|
|
||||||
public SceneDecoder (SceneReceiver receiver)
|
|
||||||
{
|
|
||||||
this.receiver = receiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public String getReceiverCode ()
|
|
||||||
{
|
|
||||||
return RECEIVER_CODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchNotification (int methodId, Object[] args)
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case FORCED_MOVE:
|
|
||||||
((SceneReceiver)receiver).forcedMove(
|
|
||||||
((Integer)args[0]).intValue()
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchNotification(methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,532 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.client;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.samskivert.util.LRUHashMap;
|
|
||||||
import com.samskivert.util.ResultListener;
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.BasicDirector;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
|
|
||||||
import com.threerings.crowd.client.LocationDirector;
|
|
||||||
import com.threerings.crowd.client.LocationObserver;
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.client.persist.SceneRepository;
|
|
||||||
import com.threerings.whirled.data.Scene;
|
|
||||||
import com.threerings.whirled.data.SceneCodes;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.util.NoSuchSceneException;
|
|
||||||
import com.threerings.whirled.util.SceneFactory;
|
|
||||||
import com.threerings.whirled.util.WhirledContext;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene director is the client's interface to all things scene
|
|
||||||
* related. It interfaces with the scene repository to ensure that scene
|
|
||||||
* objects are available when the client enters a particular scene. It
|
|
||||||
* handles moving from scene to scene (it coordinates with the {@link
|
|
||||||
* LocationDirector} in order to do this).
|
|
||||||
*
|
|
||||||
* <p> Note that when the scene director is in use instead of the location
|
|
||||||
* director, scene ids instead of place oids will be supplied to {@link
|
|
||||||
* LocationObserver#locationMayChange} and {@link
|
|
||||||
* LocationObserver#locationChangeFailed}.
|
|
||||||
*/
|
|
||||||
public class SceneDirector extends BasicDirector
|
|
||||||
implements SceneCodes, LocationDirector.FailureHandler,
|
|
||||||
SceneReceiver, SceneService.SceneMoveListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Used to recover from a problem after a completed moveTo.
|
|
||||||
*/
|
|
||||||
public static interface MoveHandler
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Should instruct the client to move the last known working
|
|
||||||
* location (as well as clean up after the failed moveTo request).
|
|
||||||
*/
|
|
||||||
public void recoverMoveTo (int sceneId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new scene director with the specified context.
|
|
||||||
*
|
|
||||||
* @param ctx the active client context.
|
|
||||||
* @param locdir the location director in use on the client, with
|
|
||||||
* which the scene director will coordinate when changing location.
|
|
||||||
* @param screp the entity from which the scene director will load
|
|
||||||
* scene data from the local client scene storage. This may be null
|
|
||||||
* when the SceneDirector is constructed, but it should be
|
|
||||||
* supplied via {@link #setSceneRepository} prior to really using
|
|
||||||
* this director.
|
|
||||||
* @param fact the factory that knows which derivation of {@link
|
|
||||||
* Scene} to create for the current system.
|
|
||||||
*/
|
|
||||||
public SceneDirector (WhirledContext ctx, LocationDirector locdir,
|
|
||||||
SceneRepository screp, SceneFactory fact)
|
|
||||||
{
|
|
||||||
super(ctx);
|
|
||||||
|
|
||||||
// we'll need these for later
|
|
||||||
_ctx = ctx;
|
|
||||||
_locdir = locdir;
|
|
||||||
setSceneRepository(screp);
|
|
||||||
_fact = fact;
|
|
||||||
|
|
||||||
// set ourselves up as a failure handler with the location
|
|
||||||
// director because we need to do special processing
|
|
||||||
_locdir.setFailureHandler(this);
|
|
||||||
|
|
||||||
// register for scene notifications
|
|
||||||
_ctx.getClient().getInvocationDirector().registerReceiver(
|
|
||||||
new SceneDecoder(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the scene repository.
|
|
||||||
*/
|
|
||||||
public void setSceneRepository (SceneRepository screp)
|
|
||||||
{
|
|
||||||
_screp = screp;
|
|
||||||
_scache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the display scene object associated with the scene we
|
|
||||||
* currently occupy or null if we currently occupy no scene.
|
|
||||||
*/
|
|
||||||
public Scene getScene ()
|
|
||||||
{
|
|
||||||
return _scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that this client move the specified scene. A request will
|
|
||||||
* be made and when the response is received, the location observers
|
|
||||||
* will be notified of success or failure.
|
|
||||||
*
|
|
||||||
* @return true if the move to request was issued, false if it was
|
|
||||||
* rejected by a location observer or because we have another request
|
|
||||||
* outstanding.
|
|
||||||
*/
|
|
||||||
public boolean moveTo (int sceneId)
|
|
||||||
{
|
|
||||||
// make sure the sceneId is valid
|
|
||||||
if (sceneId < 0) {
|
|
||||||
Log.warning("Refusing moveTo(): invalid sceneId " + sceneId + ".");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanity-check the destination scene id
|
|
||||||
if (sceneId == _sceneId) {
|
|
||||||
Log.warning("Refusing request to move to the same scene " +
|
|
||||||
"[sceneId=" + sceneId + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare to move to this scene (sets up pending data)
|
|
||||||
if (!prepareMoveTo(sceneId, null)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the version of our cached copy of the scene to which
|
|
||||||
// we're requesting to move; if we were unable to load it, assume
|
|
||||||
// a cached version of zero
|
|
||||||
int sceneVers = 0;
|
|
||||||
if (_pendingModel != null) {
|
|
||||||
sceneVers = _pendingModel.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// issue a moveTo request
|
|
||||||
Log.info("Issuing moveTo(" + sceneId + ", " + sceneVers + ").");
|
|
||||||
_sservice.moveTo(_ctx.getClient(), sceneId, sceneVers, this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares to move to the requested scene. The location observers are
|
|
||||||
* asked to ratify the move and our pending scene mode is loaded from
|
|
||||||
* the scene repository. This can be called by cooperating directors
|
|
||||||
* that need to coopt the moveTo process.
|
|
||||||
*/
|
|
||||||
public boolean prepareMoveTo (int sceneId, ResultListener rl)
|
|
||||||
{
|
|
||||||
// first check to see if our observers are happy with this move
|
|
||||||
// request
|
|
||||||
if (!_locdir.mayMoveTo(sceneId, rl)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to call this both to mark that we're issuing a move
|
|
||||||
// request and to check to see if the last issued request should
|
|
||||||
// be considered stale
|
|
||||||
boolean refuse = _locdir.checkRepeatMove();
|
|
||||||
|
|
||||||
// complain if we're over-writing a pending request
|
|
||||||
if (_pendingSceneId != -1) {
|
|
||||||
if (refuse) {
|
|
||||||
Log.warning("Refusing moveTo; We have a request outstanding " +
|
|
||||||
"[psid=" + _pendingSceneId +
|
|
||||||
", nsid=" + sceneId + "].");
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.warning("Overriding stale moveTo request " +
|
|
||||||
"[psid=" + _pendingSceneId +
|
|
||||||
", nsid=" + sceneId + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// load up the pending scene so that we can communicate it's most
|
|
||||||
// recent version to the server
|
|
||||||
_pendingModel = loadSceneModel(sceneId);
|
|
||||||
|
|
||||||
// make a note of our pending scene id
|
|
||||||
_pendingSceneId = sceneId;
|
|
||||||
|
|
||||||
// all systems go
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the model loaded in preparation for a scene
|
|
||||||
* transition. This is made available only for cooperating directors
|
|
||||||
* which may need to coopt the scene transition process. The pending
|
|
||||||
* model is only valid immediately following a call to {@link
|
|
||||||
* #prepareMoveTo}.
|
|
||||||
*/
|
|
||||||
public SceneModel getPendingModel ()
|
|
||||||
{
|
|
||||||
return _pendingModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceeded (int placeId, PlaceConfig config)
|
|
||||||
{
|
|
||||||
// our move request was successful, deal with subscribing to our
|
|
||||||
// new place object
|
|
||||||
_locdir.didMoveTo(placeId, config);
|
|
||||||
|
|
||||||
// since we're committed to moving to the new scene, we'll
|
|
||||||
// parallelize and go ahead and load up the new scene now rather
|
|
||||||
// than wait until subscription to our place object succeeds
|
|
||||||
|
|
||||||
// keep track of our previous scene info
|
|
||||||
_previousSceneId = _sceneId;
|
|
||||||
|
|
||||||
// clear out the old info
|
|
||||||
clearScene();
|
|
||||||
|
|
||||||
// make the pending scene the active scene
|
|
||||||
_sceneId = _pendingSceneId;
|
|
||||||
_pendingSceneId = -1;
|
|
||||||
|
|
||||||
// load the new scene model
|
|
||||||
_model = loadSceneModel(_sceneId);
|
|
||||||
|
|
||||||
// complain if we didn't find a scene
|
|
||||||
if (_model == null) {
|
|
||||||
Log.warning("Aiya! Unable to load scene [sid=" + _sceneId +
|
|
||||||
", plid=" + placeId + "].");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// and finally create a display scene instance with the model and
|
|
||||||
// the place config
|
|
||||||
_scene = _fact.createScene(_model, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceededWithUpdates (
|
|
||||||
int placeId, PlaceConfig config, SceneUpdate[] updates)
|
|
||||||
{
|
|
||||||
Log.info("Got updates [placeId=" + placeId + ", config=" + config +
|
|
||||||
", updates=" + StringUtil.toString(updates) + "].");
|
|
||||||
|
|
||||||
// apply the updates to our cached scene
|
|
||||||
SceneModel model = loadSceneModel(_pendingSceneId);
|
|
||||||
boolean failure = false;
|
|
||||||
for (int ii = 0; ii < updates.length; ii++) {
|
|
||||||
try {
|
|
||||||
updates[ii].validate(model);
|
|
||||||
} catch (IllegalStateException ise) {
|
|
||||||
Log.warning("Scene update failed validation [model=" + model +
|
|
||||||
", update=" + updates[ii] +
|
|
||||||
", error=" + ise.getMessage() + "].");
|
|
||||||
failure = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
updates[ii].apply(model);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.warning("Failure applying scene update [model=" + model +
|
|
||||||
", update=" + updates[ii] + "].");
|
|
||||||
Log.logStackTrace(e);
|
|
||||||
failure = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failure) {
|
|
||||||
// delete the now half-booched scene model from the repository
|
|
||||||
try {
|
|
||||||
_screp.deleteSceneModel(_pendingSceneId);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
Log.warning("Failure removing booched scene model " +
|
|
||||||
"[sceneId=" + _pendingSceneId + "].");
|
|
||||||
Log.logStackTrace(ioe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// act as if the scene move failed, though we'll be in a funny
|
|
||||||
// state because the server thinks we've changed scenes, but
|
|
||||||
// the client can try again without its booched scene model
|
|
||||||
requestFailed(INTERNAL_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// store the updated scene in the repository
|
|
||||||
try {
|
|
||||||
_screp.storeSceneModel(model);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
Log.warning("Failed to update repository with updated scene " +
|
|
||||||
"[sceneId=" + model.sceneId + "].");
|
|
||||||
Log.logStackTrace(ioe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally pass through to the normal success handler
|
|
||||||
moveSucceeded(placeId, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceededWithScene (
|
|
||||||
int placeId, PlaceConfig config, SceneModel model)
|
|
||||||
{
|
|
||||||
Log.info("Got updated scene model [placeId=" + placeId +
|
|
||||||
", config=" + config + ", scene=" + model.sceneId + "/" +
|
|
||||||
model.name + "/" + model.version + "].");
|
|
||||||
|
|
||||||
// update the model in the repository
|
|
||||||
try {
|
|
||||||
_screp.storeSceneModel(model);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
Log.warning("Failed to update repository with new version " +
|
|
||||||
"[sceneId=" + model.sceneId +
|
|
||||||
", nvers=" + model.version + "].");
|
|
||||||
Log.logStackTrace(ioe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update our scene cache
|
|
||||||
_scache.put(Integer.valueOf(model.sceneId), model);
|
|
||||||
|
|
||||||
// and pass through to the normal move succeeded handler
|
|
||||||
moveSucceeded(placeId, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void requestFailed (String reason)
|
|
||||||
{
|
|
||||||
// clear out our pending request oid
|
|
||||||
int sceneId = _pendingSceneId;
|
|
||||||
_pendingSceneId = -1;
|
|
||||||
|
|
||||||
// let our observers know that something has gone horribly awry
|
|
||||||
_locdir.failedToMoveTo(sceneId, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to clean up our place and scene state information when we
|
|
||||||
* leave a scene.
|
|
||||||
*/
|
|
||||||
public void didLeaveScene ()
|
|
||||||
{
|
|
||||||
// let the location director know what's up
|
|
||||||
_locdir.didLeavePlace();
|
|
||||||
|
|
||||||
// clear out our own scene state
|
|
||||||
clearScene();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void forcedMove (int sceneId)
|
|
||||||
{
|
|
||||||
Log.info("Moving at request of server [sceneId=" + sceneId + "].");
|
|
||||||
|
|
||||||
// clear out our old scene and place data
|
|
||||||
didLeaveScene();
|
|
||||||
|
|
||||||
// move to the new scene
|
|
||||||
moveTo(sceneId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the moveHandler for use in recoverFailedMove.
|
|
||||||
*/
|
|
||||||
public void setMoveHandler (MoveHandler handler)
|
|
||||||
{
|
|
||||||
if (_moveHandler != null) {
|
|
||||||
Log.warning("Requested to set move handler, but we've " +
|
|
||||||
"already got one. The conflicting entities will " +
|
|
||||||
"likely need to perform more sophisticated " +
|
|
||||||
"coordination to deal with failures. " +
|
|
||||||
"[old=" + _moveHandler + ", new=" + handler + "].");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_moveHandler = handler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when something breaks down in the process of performing a
|
|
||||||
* <code>moveTo</code> request.
|
|
||||||
*/
|
|
||||||
public void recoverFailedMove (int placeId)
|
|
||||||
{
|
|
||||||
// we'll need this momentarily
|
|
||||||
int sceneId = _sceneId;
|
|
||||||
|
|
||||||
// clear out our now bogus scene tracking info
|
|
||||||
clearScene();
|
|
||||||
|
|
||||||
// if we were previously somewhere (and that somewhere isn't where
|
|
||||||
// we just tried to go), try going back to that happy place
|
|
||||||
if (_previousSceneId != -1 && _previousSceneId != sceneId) {
|
|
||||||
// if we have a move handler use that
|
|
||||||
if (_moveHandler != null) {
|
|
||||||
_moveHandler.recoverMoveTo(_previousSceneId);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
moveTo(_previousSceneId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears out our current scene information and releases the scene
|
|
||||||
* model for the loaded scene back to the cache.
|
|
||||||
*/
|
|
||||||
protected void clearScene ()
|
|
||||||
{
|
|
||||||
// clear out our scene id info
|
|
||||||
_sceneId = -1;
|
|
||||||
|
|
||||||
// clear out our references
|
|
||||||
_model = null;
|
|
||||||
_scene = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a scene from the repository. If the scene is cached, it will
|
|
||||||
* be returned from the cache instead.
|
|
||||||
*/
|
|
||||||
protected SceneModel loadSceneModel (int sceneId)
|
|
||||||
{
|
|
||||||
// first look in the model cache
|
|
||||||
Integer key = Integer.valueOf(sceneId);
|
|
||||||
SceneModel model = (SceneModel)_scache.get(key);
|
|
||||||
|
|
||||||
// load from the repository if it's not cached
|
|
||||||
if (model == null) {
|
|
||||||
try {
|
|
||||||
model = _screp.loadSceneModel(sceneId);
|
|
||||||
_scache.put(key, model);
|
|
||||||
|
|
||||||
} catch (NoSuchSceneException nsse) {
|
|
||||||
// nothing special here, just fall through and return null
|
|
||||||
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
// complain first, then return null
|
|
||||||
Log.warning("Error loading scene [scid=" + sceneId +
|
|
||||||
", error=" + ioe + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void clientDidLogoff (Client client)
|
|
||||||
{
|
|
||||||
super.clientDidLogoff(client);
|
|
||||||
|
|
||||||
// clear out our business
|
|
||||||
clearScene();
|
|
||||||
_scache.clear();
|
|
||||||
_pendingSceneId = -1;
|
|
||||||
_pendingModel = null;
|
|
||||||
_previousSceneId = -1;
|
|
||||||
_sservice = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
protected void fetchServices (Client client)
|
|
||||||
{
|
|
||||||
// get a handle on our scene service
|
|
||||||
_sservice = (SceneService)client.requireService(SceneService.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Access to general client services. */
|
|
||||||
protected WhirledContext _ctx;
|
|
||||||
|
|
||||||
/** Access to our scene services. */
|
|
||||||
protected SceneService _sservice;
|
|
||||||
|
|
||||||
/** The client's active location director. */
|
|
||||||
protected LocationDirector _locdir;
|
|
||||||
|
|
||||||
/** The entity via which we load scene data. */
|
|
||||||
protected SceneRepository _screp;
|
|
||||||
|
|
||||||
/** The entity we use to create scenes from scene models. */
|
|
||||||
protected SceneFactory _fact;
|
|
||||||
|
|
||||||
/** A cache of scene model information. */
|
|
||||||
protected LRUHashMap _scache = new LRUHashMap(5);
|
|
||||||
|
|
||||||
/** The display scene object for the scene we currently occupy. */
|
|
||||||
protected Scene _scene;
|
|
||||||
|
|
||||||
/** The scene model for the scene we currently occupy. */
|
|
||||||
protected SceneModel _model;
|
|
||||||
|
|
||||||
/** The id of the scene we currently occupy. */
|
|
||||||
protected int _sceneId = -1;
|
|
||||||
|
|
||||||
/** Our most recent copy of the scene model for the scene we're about
|
|
||||||
* to enter. */
|
|
||||||
protected SceneModel _pendingModel;
|
|
||||||
|
|
||||||
/** The id of the scene for which we have an outstanding moveTo
|
|
||||||
* request, or -1 if we have no outstanding request. */
|
|
||||||
protected int _pendingSceneId = -1;
|
|
||||||
|
|
||||||
/** The id of the scene we previously occupied. */
|
|
||||||
protected int _previousSceneId = -1;
|
|
||||||
|
|
||||||
/** Reference to our move handler. */
|
|
||||||
protected MoveHandler _moveHandler = null;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.InvocationReceiver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines, for the scene services, a set of notifications delivered
|
|
||||||
* asynchronously by the server to the client.
|
|
||||||
*/
|
|
||||||
public interface SceneReceiver extends InvocationReceiver
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Used to communicate a required move notification to the client. The
|
|
||||||
* server will have removed the client from their existing scene
|
|
||||||
* and the client is then responsible for generating a {@link
|
|
||||||
* SceneService#moveTo} request to move to the new scene.
|
|
||||||
*/
|
|
||||||
public void forcedMove (int sceneId);
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.client.InvocationService;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene service class provides the client interface to the scene
|
|
||||||
* related invocation services (e.g. moving from scene to scene).
|
|
||||||
*/
|
|
||||||
public interface SceneService extends InvocationService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Used to communicate the response to a {@link #moveTo} request.
|
|
||||||
*/
|
|
||||||
public static interface SceneMoveListener extends InvocationListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Indicates that a move succeeded.
|
|
||||||
*
|
|
||||||
* @param placeId the place object id of the newly occupied scene.
|
|
||||||
* @param config metadata related to the newly occupied scene.
|
|
||||||
*/
|
|
||||||
public void moveSucceeded (int placeId, PlaceConfig config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that a move succeeded and that the client's cached
|
|
||||||
* scene information should be updated with the supplied data.
|
|
||||||
*
|
|
||||||
* @param placeId the place object id of the newly occupied scene.
|
|
||||||
* @param config metadata related to the newly occupied scene.
|
|
||||||
* @param updates updates that must be applied to the client's
|
|
||||||
* copy of a scene model to bring it up to date.
|
|
||||||
*/
|
|
||||||
public void moveSucceededWithUpdates (int placeId, PlaceConfig config,
|
|
||||||
SceneUpdate[] updates);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that a move succeeded and that the client's cached
|
|
||||||
* scene information should be updated with the supplied data.
|
|
||||||
*
|
|
||||||
* @param placeId the place object id of the newly occupied scene.
|
|
||||||
* @param config metadata related to the newly occupied scene.
|
|
||||||
* @param model a fresh copy of the most recent scene data for the
|
|
||||||
* newly occupied scene.
|
|
||||||
*/
|
|
||||||
public void moveSucceededWithScene (int placeId, PlaceConfig config,
|
|
||||||
SceneModel model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that that this client's body be moved to the specified
|
|
||||||
* scene.
|
|
||||||
*
|
|
||||||
* @param sceneId the scene id to which we want to move.
|
|
||||||
* @param version the version number of the scene object that we have
|
|
||||||
* in our local repository.
|
|
||||||
*/
|
|
||||||
public void moveTo (Client client, int sceneId, int version,
|
|
||||||
SceneMoveListener listener);
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.client.persist;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.util.NoSuchSceneException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene repository provides access to a persistent repository of
|
|
||||||
* scene information.
|
|
||||||
*
|
|
||||||
* @see SceneModel
|
|
||||||
*/
|
|
||||||
public interface SceneRepository
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Fetches the model for the scene with the specified id.
|
|
||||||
*
|
|
||||||
* @exception IOException thrown if an error occurs attempting to load
|
|
||||||
* the scene data.
|
|
||||||
* @exception NoSuchSceneException thrown if no scene exists with the
|
|
||||||
* specified scene id.
|
|
||||||
*/
|
|
||||||
public SceneModel loadSceneModel (int sceneId)
|
|
||||||
throws IOException, NoSuchSceneException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates or inserts this scene model as appropriate.
|
|
||||||
*
|
|
||||||
* @exception IOException thrown if an error occurs attempting to
|
|
||||||
* access the repository.
|
|
||||||
*/
|
|
||||||
public void storeSceneModel (SceneModel model)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the specified scene model from the repository.
|
|
||||||
*
|
|
||||||
* @exception IOException thrown if an error occurs attempting to
|
|
||||||
* access the repository.
|
|
||||||
*/
|
|
||||||
public void deleteSceneModel (int sceneId)
|
|
||||||
throws IOException;
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import com.threerings.io.Streamable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface that must be implemented by auxiliary scene models.
|
|
||||||
*/
|
|
||||||
public interface AuxModel extends Streamable, Cloneable
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a clone of this auxiliary model.
|
|
||||||
*/
|
|
||||||
public Object clone ()
|
|
||||||
throws CloneNotSupportedException;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.whirled.client.SceneController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default scene config simply causes the default scene manager and
|
|
||||||
* controller to be created. A user of the Whirled services would most
|
|
||||||
* likely extend the default scene config.
|
|
||||||
*
|
|
||||||
* <p> Note that this place config won't even work on the client side
|
|
||||||
* because it instantiates a {@link SceneController} which is an abstract
|
|
||||||
* class. It is used only for testing the server side and as a placeholder
|
|
||||||
* in case standard scene configuration information is one day needed.
|
|
||||||
*/
|
|
||||||
public class DefaultSceneConfig extends PlaceConfig
|
|
||||||
{
|
|
||||||
// documentation inherited
|
|
||||||
public String getManagerClassName ()
|
|
||||||
{
|
|
||||||
return "com.threerings.whirled.server.SceneManager";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface makes available basic scene information. At this basic
|
|
||||||
* level, not much information is available, but extensions to this
|
|
||||||
* interface begin to create a more comprehensive picture of a scene in a
|
|
||||||
* system built from the Whirled services.
|
|
||||||
*/
|
|
||||||
public interface Scene
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns the unique identifier for this scene.
|
|
||||||
*/
|
|
||||||
public int getId ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the human readable name of this scene.
|
|
||||||
*/
|
|
||||||
public String getName ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the version number of this scene.
|
|
||||||
*/
|
|
||||||
public int getVersion ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the place config that can be used to determine which place
|
|
||||||
* controller instance should be used to display this scene as well as
|
|
||||||
* to obtain runtime configuration information.
|
|
||||||
*/
|
|
||||||
public PlaceConfig getPlaceConfig ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets this scene's unique identifier.
|
|
||||||
*/
|
|
||||||
public void setId (int sceneId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the human readable name of this scene.
|
|
||||||
*/
|
|
||||||
public void setName (String name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets this scene's version number.
|
|
||||||
*/
|
|
||||||
public void setVersion (int version);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to inform the scene that an update has been received while
|
|
||||||
* the scene was resolved and active. The update should be applied to
|
|
||||||
* the underlying scene model and any derivative data should be
|
|
||||||
* appropriately updated.
|
|
||||||
*/
|
|
||||||
public void updateReceived (SceneUpdate update);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the scene model from which this scene was created.
|
|
||||||
*/
|
|
||||||
public SceneModel getSceneModel ();
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.LocationCodes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains codes used by the scene invocation services.
|
|
||||||
*/
|
|
||||||
public interface SceneCodes extends LocationCodes
|
|
||||||
{
|
|
||||||
/** The message identifier for scene update messages. */
|
|
||||||
public static final String SCENE_UPDATE = "scene_update";
|
|
||||||
}
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of the {@link Scene} interface.
|
|
||||||
*/
|
|
||||||
public class SceneImpl implements Scene
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates an instance that will obtain data from the supplied scene
|
|
||||||
* model and place config.
|
|
||||||
*/
|
|
||||||
public SceneImpl (SceneModel model, PlaceConfig config)
|
|
||||||
{
|
|
||||||
_model = model;
|
|
||||||
_config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a blank scene implementation. No place config will be
|
|
||||||
* associated with this scene.
|
|
||||||
*/
|
|
||||||
public SceneImpl ()
|
|
||||||
{
|
|
||||||
_model = SceneModel.blankSceneModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public int getId ()
|
|
||||||
{
|
|
||||||
return _model.sceneId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public String getName ()
|
|
||||||
{
|
|
||||||
return _model.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public int getVersion ()
|
|
||||||
{
|
|
||||||
return _model.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public PlaceConfig getPlaceConfig ()
|
|
||||||
{
|
|
||||||
return _config;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void setId (int sceneId)
|
|
||||||
{
|
|
||||||
_model.sceneId = sceneId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void setName (String name)
|
|
||||||
{
|
|
||||||
_model.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void setVersion (int version)
|
|
||||||
{
|
|
||||||
_model.version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void updateReceived (SceneUpdate update)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// validate and apply the update
|
|
||||||
update.validate(_model);
|
|
||||||
update.apply(_model);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.warning("Error applying update [scene=" + this +
|
|
||||||
", update=" + update + "].");
|
|
||||||
Log.logStackTrace(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public SceneModel getSceneModel ()
|
|
||||||
{
|
|
||||||
return _model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a string representation of this instance.
|
|
||||||
*/
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return "[model=" + _model + ", config=" + _config + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A reference to our scene model. */
|
|
||||||
protected SceneModel _model;
|
|
||||||
|
|
||||||
/** A reference to our place configuration. */
|
|
||||||
protected PlaceConfig _config;
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
|
||||||
import com.threerings.whirled.client.SceneService;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the implementation of the {@link SceneService} interface
|
|
||||||
* that marshalls the arguments and delivers the request to the provider
|
|
||||||
* on the server. Also provides an implementation of the response listener
|
|
||||||
* interfaces that marshall the response arguments and deliver them back
|
|
||||||
* to the requesting client.
|
|
||||||
*/
|
|
||||||
public class SceneMarshaller extends InvocationMarshaller
|
|
||||||
implements SceneService
|
|
||||||
{
|
|
||||||
// documentation inherited
|
|
||||||
public static class SceneMoveMarshaller extends ListenerMarshaller
|
|
||||||
implements SceneMoveListener
|
|
||||||
{
|
|
||||||
/** The method id used to dispatch {@link #moveSucceeded}
|
|
||||||
* responses. */
|
|
||||||
public static final int MOVE_SUCCEEDED = 1;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceeded (int arg1, PlaceConfig arg2)
|
|
||||||
{
|
|
||||||
_invId = null;
|
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
|
||||||
callerOid, requestId, MOVE_SUCCEEDED,
|
|
||||||
new Object[] { Integer.valueOf(arg1), arg2 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #moveSucceededWithScene}
|
|
||||||
* responses. */
|
|
||||||
public static final int MOVE_SUCCEEDED_WITH_SCENE = 2;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceededWithScene (int arg1, PlaceConfig arg2, SceneModel arg3)
|
|
||||||
{
|
|
||||||
_invId = null;
|
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
|
||||||
callerOid, requestId, MOVE_SUCCEEDED_WITH_SCENE,
|
|
||||||
new Object[] { Integer.valueOf(arg1), arg2, arg3 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #moveSucceededWithUpdates}
|
|
||||||
* responses. */
|
|
||||||
public static final int MOVE_SUCCEEDED_WITH_UPDATES = 3;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceededWithUpdates (int arg1, PlaceConfig arg2, SceneUpdate[] arg3)
|
|
||||||
{
|
|
||||||
_invId = null;
|
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
|
||||||
callerOid, requestId, MOVE_SUCCEEDED_WITH_UPDATES,
|
|
||||||
new Object[] { Integer.valueOf(arg1), arg2, arg3 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchResponse (int methodId, Object[] args)
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case MOVE_SUCCEEDED:
|
|
||||||
((SceneMoveListener)listener).moveSucceeded(
|
|
||||||
((Integer)args[0]).intValue(), (PlaceConfig)args[1]);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case MOVE_SUCCEEDED_WITH_SCENE:
|
|
||||||
((SceneMoveListener)listener).moveSucceededWithScene(
|
|
||||||
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (SceneModel)args[2]);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case MOVE_SUCCEEDED_WITH_UPDATES:
|
|
||||||
((SceneMoveListener)listener).moveSucceededWithUpdates(
|
|
||||||
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (SceneUpdate[])args[2]);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchResponse(methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #moveTo} requests. */
|
|
||||||
public static final int MOVE_TO = 1;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveTo (Client arg1, int arg2, int arg3, SceneService.SceneMoveListener arg4)
|
|
||||||
{
|
|
||||||
SceneMarshaller.SceneMoveMarshaller listener4 = new SceneMarshaller.SceneMoveMarshaller();
|
|
||||||
listener4.listener = arg4;
|
|
||||||
sendRequest(arg1, MOVE_TO, new Object[] {
|
|
||||||
Integer.valueOf(arg2), Integer.valueOf(arg3), listener4
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import com.samskivert.util.ArrayUtil;
|
|
||||||
|
|
||||||
import com.threerings.io.SimpleStreamableObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene model is the bare bones representation of the data for a
|
|
||||||
* scene in the Whirled system. From the scene model, one would create an
|
|
||||||
* instance of {@link Scene}.
|
|
||||||
*
|
|
||||||
* <p> The scene model is what is loaded from the scene repositories and
|
|
||||||
* what is transmitted over the wire when communicating scenes from the
|
|
||||||
* server to the client.
|
|
||||||
*/
|
|
||||||
public class SceneModel extends SimpleStreamableObject
|
|
||||||
implements Cloneable
|
|
||||||
{
|
|
||||||
/** This scene's unique identifier. */
|
|
||||||
public int sceneId;
|
|
||||||
|
|
||||||
/** The human readable name of this scene. */
|
|
||||||
public String name;
|
|
||||||
|
|
||||||
/** The version number of this scene. Versions are incremented
|
|
||||||
* whenever modifications are made to a scene so that clients can
|
|
||||||
* determine whether or not they have the latest version of a
|
|
||||||
* scene. */
|
|
||||||
public int version;
|
|
||||||
|
|
||||||
/** Auxiliary scene model information. */
|
|
||||||
public AuxModel[] auxModels = new AuxModel[0];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specified auxiliary model to this scene model.
|
|
||||||
*/
|
|
||||||
public void addAuxModel (AuxModel auxModel)
|
|
||||||
{
|
|
||||||
auxModels = (AuxModel[])ArrayUtil.append(auxModels, auxModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public Object clone ()
|
|
||||||
throws CloneNotSupportedException
|
|
||||||
{
|
|
||||||
SceneModel model = (SceneModel)super.clone();
|
|
||||||
model.auxModels = new AuxModel[auxModels.length];
|
|
||||||
for (int ii = 0; ii < auxModels.length; ii++) {
|
|
||||||
model.auxModels[ii] = (AuxModel)auxModels[ii].clone();
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a blank scene model.
|
|
||||||
*/
|
|
||||||
public static SceneModel blankSceneModel ()
|
|
||||||
{
|
|
||||||
SceneModel model = new SceneModel();
|
|
||||||
populateBlankSceneModel(model);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates a blank scene model with blank values.
|
|
||||||
*/
|
|
||||||
protected static void populateBlankSceneModel (SceneModel model)
|
|
||||||
{
|
|
||||||
model.sceneId = -1;
|
|
||||||
model.name = "<blank>";
|
|
||||||
model.version = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceObject;
|
|
||||||
|
|
||||||
public class SceneObject extends PlaceObject
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.threerings.io.ObjectInputStream;
|
|
||||||
import com.threerings.io.ObjectOutputStream;
|
|
||||||
import com.threerings.io.Streamable;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to encapsulate updates to scenes in such a manner that updates can
|
|
||||||
* be stored persistently and sent to clients to update their own local
|
|
||||||
* copies of scenes.
|
|
||||||
*/
|
|
||||||
public class SceneUpdate
|
|
||||||
implements Streamable, Cloneable
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Initializes this scene update such that it will operate on a scene
|
|
||||||
* with the specified target scene and version number.
|
|
||||||
*
|
|
||||||
* @param targetId the id of the scene on which we are to operate.
|
|
||||||
* @param targetVersion the version of the scene on which we are to
|
|
||||||
* operate.
|
|
||||||
*/
|
|
||||||
public void init (int targetId, int targetVersion)
|
|
||||||
{
|
|
||||||
_targetId = targetId;
|
|
||||||
_targetVersion = targetVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the scene id for which this update is appropriate.
|
|
||||||
*/
|
|
||||||
public int getSceneId ()
|
|
||||||
{
|
|
||||||
return _targetId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the scene version for which this update is appropriate.
|
|
||||||
*/
|
|
||||||
public int getSceneVersion ()
|
|
||||||
{
|
|
||||||
return _targetVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to ensure that the scene is in the appropriate state prior
|
|
||||||
* to applying the update.
|
|
||||||
*
|
|
||||||
* @exception IllegalStateException thrown if the update cannot be
|
|
||||||
* applied to the scene because it is not in a valid state
|
|
||||||
* (appropriate previous updates were not applied, it's the wrong kind
|
|
||||||
* of scene, etc.).
|
|
||||||
*/
|
|
||||||
public void validate (SceneModel model)
|
|
||||||
throws IllegalStateException
|
|
||||||
{
|
|
||||||
if (model.sceneId != _targetId) {
|
|
||||||
String errmsg = "Wrong target scene, expected id " +
|
|
||||||
_targetId + " got id " + model.sceneId;
|
|
||||||
throw new IllegalStateException(errmsg);
|
|
||||||
}
|
|
||||||
if (model.version != _targetVersion) {
|
|
||||||
String errmsg = "Target scene not proper version, expected " +
|
|
||||||
_targetVersion + " got " + model.version;
|
|
||||||
throw new IllegalStateException(errmsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies this update to the specified scene model. Derived classes
|
|
||||||
* will want to override this method and apply updates of their own,
|
|
||||||
* being sure to call <code>super.apply</code>.
|
|
||||||
*/
|
|
||||||
public void apply (SceneModel model)
|
|
||||||
{
|
|
||||||
// increment the version; disallowing integer overflow
|
|
||||||
model.version = Math.max(_targetVersion + 1, model.version);
|
|
||||||
|
|
||||||
// sanity check for the amazing two billion updates
|
|
||||||
if (model.version == _targetVersion) {
|
|
||||||
Log.warning("Egads! This scene has been updated two billion " +
|
|
||||||
"times [model=" + model + ", update=" + this + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes our custom streamable fields.
|
|
||||||
*/
|
|
||||||
public void writeObject (ObjectOutputStream out)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
if (null == _dbSer.get()) {
|
|
||||||
out.writeInt(_targetId);
|
|
||||||
out.writeInt(_targetVersion);
|
|
||||||
}
|
|
||||||
out.defaultWriteObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads our custom streamable fields.
|
|
||||||
*/
|
|
||||||
public void readObject (ObjectInputStream in)
|
|
||||||
throws IOException, ClassNotFoundException
|
|
||||||
{
|
|
||||||
if (null == _dbSer.get()) {
|
|
||||||
_targetId = in.readInt();
|
|
||||||
_targetVersion = in.readInt();
|
|
||||||
}
|
|
||||||
in.defaultReadObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializes the bare representation of this instance without the scene id
|
|
||||||
* and version fields. Useful when storing updates in a database where the
|
|
||||||
* scene id and version fields are stored in separate columns and the rest
|
|
||||||
* if the representation is contained in an opaque blob.
|
|
||||||
*/
|
|
||||||
public void persistTo (ObjectOutputStream out)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
_dbSer.set(Boolean.TRUE);
|
|
||||||
try {
|
|
||||||
out.writeBareObject(this);
|
|
||||||
} finally {
|
|
||||||
_dbSer.set(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unserializes this instance from the bare representation created by
|
|
||||||
* {@link #persistTo}.
|
|
||||||
*/
|
|
||||||
public void unpersistFrom (ObjectInputStream in)
|
|
||||||
throws IOException, ClassNotFoundException
|
|
||||||
{
|
|
||||||
_dbSer.set(Boolean.TRUE);
|
|
||||||
try {
|
|
||||||
in.readBareObject(this);
|
|
||||||
} finally {
|
|
||||||
_dbSer.set(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a string representation of this instance.
|
|
||||||
*/
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
StringBuilder buf = new StringBuilder("[");
|
|
||||||
toString(buf);
|
|
||||||
return buf.append("]").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An extensible mechanism for generating a string representation of
|
|
||||||
* this instance.
|
|
||||||
*/
|
|
||||||
protected void toString (StringBuilder buf)
|
|
||||||
{
|
|
||||||
buf.append("sceneId=").append(_targetId);
|
|
||||||
buf.append(", version=").append(_targetVersion);
|
|
||||||
buf.append(", ");
|
|
||||||
StringUtil.fieldsToString(buf, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The version number of the scene on which we operate. */
|
|
||||||
protected transient int _targetId;
|
|
||||||
|
|
||||||
/** The version number of the scene on which we operate. */
|
|
||||||
protected transient int _targetVersion;
|
|
||||||
|
|
||||||
/** Used when serializing this update for storage in the database. */
|
|
||||||
protected static ThreadLocal _dbSer = new ThreadLocal();
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A system that uses the whirled services must provide a body object
|
|
||||||
* extension that implements this interface.
|
|
||||||
*/
|
|
||||||
public interface ScenedBodyObject
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns the scene id currently occupied by this body.
|
|
||||||
*/
|
|
||||||
public int getSceneId ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the scene id currently occupied by this body.
|
|
||||||
*/
|
|
||||||
public void setSceneId (int sceneId);
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.server;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.server.InvocationDispatcher;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
import com.threerings.whirled.client.SceneService;
|
|
||||||
import com.threerings.whirled.data.SceneMarshaller;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches requests to the {@link SceneProvider}.
|
|
||||||
*/
|
|
||||||
public class SceneDispatcher extends InvocationDispatcher
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a dispatcher that may be registered to dispatch invocation
|
|
||||||
* service requests for the specified provider.
|
|
||||||
*/
|
|
||||||
public SceneDispatcher (SceneProvider provider)
|
|
||||||
{
|
|
||||||
this.provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public InvocationMarshaller createMarshaller ()
|
|
||||||
{
|
|
||||||
return new SceneMarshaller();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchRequest (
|
|
||||||
ClientObject source, int methodId, Object[] args)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case SceneMarshaller.MOVE_TO:
|
|
||||||
((SceneProvider)provider).moveTo(
|
|
||||||
source,
|
|
||||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (SceneService.SceneMoveListener)args[2]
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchRequest(source, methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.server;
|
|
||||||
|
|
||||||
import com.samskivert.io.PersistenceException;
|
|
||||||
import com.samskivert.util.Invoker;
|
|
||||||
|
|
||||||
import com.threerings.crowd.server.PlaceManager;
|
|
||||||
import com.threerings.presents.server.PresentsServer;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.data.Scene;
|
|
||||||
import com.threerings.whirled.data.SceneCodes;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.server.WhirledServer;
|
|
||||||
import com.threerings.whirled.util.UpdateList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene manager extends the place manager and takes care of basic
|
|
||||||
* scene services. Presently that is little more than registering the
|
|
||||||
* scene manager with the scene registry so that the manager can be looked
|
|
||||||
* up by scene id in addition to place object id.
|
|
||||||
*/
|
|
||||||
public class SceneManager extends PlaceManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns the scene object (not the scene distributed object) being
|
|
||||||
* managed by this scene manager.
|
|
||||||
*/
|
|
||||||
public Scene getScene ()
|
|
||||||
{
|
|
||||||
return _scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns {@link UpdateList#getUpdates} for this scene's updates.
|
|
||||||
*/
|
|
||||||
public SceneUpdate[] getUpdates (int fromVersion)
|
|
||||||
{
|
|
||||||
return _updates.getUpdates(fromVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the scene registry once the scene manager has been
|
|
||||||
* created (and initialized), but before it is started up.
|
|
||||||
*/
|
|
||||||
protected void setSceneData (Scene scene, UpdateList updates,
|
|
||||||
SceneRegistry screg)
|
|
||||||
{
|
|
||||||
_scene = scene;
|
|
||||||
_screg = screg;
|
|
||||||
_updates = updates;
|
|
||||||
|
|
||||||
// make sure the list and our version of the scene are in
|
|
||||||
// accordance
|
|
||||||
if (!_updates.validate(scene.getVersion())) {
|
|
||||||
Log.warning("Provided with invalid updates; flushing " +
|
|
||||||
"[where=" + where() +
|
|
||||||
", sceneId=" + scene.getId() + "].");
|
|
||||||
// clear out the update list as it will not allow us to bring
|
|
||||||
// clients up to date with our current scene version; instead
|
|
||||||
// they'll have to download the whole thing
|
|
||||||
_updates = new UpdateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// let derived classes react to the receipt of scene data
|
|
||||||
gotSceneData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A method that can be overridden by derived classes to perform
|
|
||||||
* initialization processing after we receive our scene information
|
|
||||||
* but before we're started up (and hence registered as an active
|
|
||||||
* place).
|
|
||||||
*/
|
|
||||||
protected void gotSceneData ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We're fully ready to go, so now we register ourselves with the
|
|
||||||
* scene registry which will make us available to the clients and
|
|
||||||
* system at large.
|
|
||||||
*/
|
|
||||||
protected void didStartup ()
|
|
||||||
{
|
|
||||||
super.didStartup();
|
|
||||||
|
|
||||||
// Wait until us and all of our subclasses have completely finished
|
|
||||||
// running didStartup prior to registering the scene as being ready.
|
|
||||||
PresentsServer.omgr.postRunnable(new Runnable() {
|
|
||||||
public void run () {
|
|
||||||
_screg.sceneManagerDidStart(SceneManager.this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when we have shutdown.
|
|
||||||
*/
|
|
||||||
protected void didShutdown ()
|
|
||||||
{
|
|
||||||
super.didShutdown();
|
|
||||||
|
|
||||||
// unregister ourselves with the scene registry
|
|
||||||
_screg.unmapSceneManager(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When a modification is made to a scene, the scene manager should
|
|
||||||
* create a SceneUpdate instance and pass it to this method which will
|
|
||||||
* update the in-memory scene, and apply and record the update in the
|
|
||||||
* scene repository.
|
|
||||||
*
|
|
||||||
* <p> This update will be stored persistently and provided (along
|
|
||||||
* with any other accumulated updates) to clients that later request
|
|
||||||
* to enter the scene with an old version of the scene data. Updates
|
|
||||||
* are not stored forever, but a sizable number of recent updates are
|
|
||||||
* stored so that moderately current clients can apply incremental
|
|
||||||
* patches to their scenes rather than redownloading entire scenes
|
|
||||||
* when they change.
|
|
||||||
*/
|
|
||||||
protected void recordUpdate (final SceneUpdate update)
|
|
||||||
{
|
|
||||||
// instruct our in-memory copy of the scene to apply the update
|
|
||||||
_scene.updateReceived(update);
|
|
||||||
|
|
||||||
// add it to our in memory update list
|
|
||||||
_updates.addUpdate(update);
|
|
||||||
|
|
||||||
// and apply and store it in the repository
|
|
||||||
WhirledServer.invoker.postUnit(new Invoker.Unit() {
|
|
||||||
public boolean invoke () {
|
|
||||||
try {
|
|
||||||
_screg.getSceneRepository().applyAndRecordUpdate(
|
|
||||||
_scene.getSceneModel(), update);
|
|
||||||
} catch (PersistenceException pe) {
|
|
||||||
Log.warning("Failed to apply scene update " + update + ".");
|
|
||||||
Log.logStackTrace(pe);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// broadcast the update to all occupants of the scene
|
|
||||||
_plobj.postMessage(SceneCodes.SCENE_UPDATE, new Object[] { update });
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public String where ()
|
|
||||||
{
|
|
||||||
return _scene.getName() + " (" + super.where() + ":" +
|
|
||||||
_scene.getId() + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void toString (StringBuilder buf)
|
|
||||||
{
|
|
||||||
super.toString(buf);
|
|
||||||
buf.append(", scene=").append(_scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A reference to our scene implementation which provides a
|
|
||||||
* meaningful interpretation of the data in the scene model. */
|
|
||||||
protected Scene _scene;
|
|
||||||
|
|
||||||
/** A list of the updates tracked for this scene. These will be used
|
|
||||||
* to attempt to bring clients up to date efficiently if they request
|
|
||||||
* to enter our scene with old scene model data. */
|
|
||||||
protected UpdateList _updates;
|
|
||||||
|
|
||||||
/** A reference to the scene registry so that we can call back to it
|
|
||||||
* when we're fully initialized. */
|
|
||||||
protected SceneRegistry _screg;
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.server;
|
|
||||||
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
import com.threerings.presents.server.InvocationProvider;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.BodyObject;
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.crowd.server.LocationProvider;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.client.SceneService.SceneMoveListener;
|
|
||||||
import com.threerings.whirled.data.SceneCodes;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.data.ScenedBodyObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene provider handles the server side of the scene related
|
|
||||||
* invocation services (e.g. moving from scene to scene).
|
|
||||||
*/
|
|
||||||
public class SceneProvider
|
|
||||||
implements InvocationProvider, SceneCodes
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Constructs a scene provider that will interact with the supplied
|
|
||||||
* scene registry.
|
|
||||||
*/
|
|
||||||
public SceneProvider (LocationProvider locprov, SceneRegistry screg)
|
|
||||||
{
|
|
||||||
_locprov = locprov;
|
|
||||||
_screg = screg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a request from a client to move to a new scene.
|
|
||||||
*/
|
|
||||||
public void moveTo (ClientObject caller, int sceneId,
|
|
||||||
final int sceneVer, final SceneMoveListener listener)
|
|
||||||
{
|
|
||||||
final BodyObject source = (BodyObject)caller;
|
|
||||||
|
|
||||||
// create a callback object that will handle the resolution or
|
|
||||||
// failed resolution of the scene
|
|
||||||
SceneRegistry.ResolutionListener rl = null;
|
|
||||||
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 (!source.isActive()) {
|
|
||||||
Log.info("Abandoning scene move, client gone " +
|
|
||||||
"[who=" + source.who() +
|
|
||||||
", dest=" + scmgr.where() + "].");
|
|
||||||
InvocationMarshaller.setNoResponse(listener);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
finishMoveToRequest(source, scmgr, sceneVer, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sceneFailedToResolve (int rsceneId, Exception reason) {
|
|
||||||
Log.warning("Unable to resolve scene [sceneid=" + rsceneId +
|
|
||||||
", reason=" + reason + "].");
|
|
||||||
// pretend like the scene doesn't exist to the client
|
|
||||||
listener.requestFailed(NO_SUCH_PLACE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// make sure the scene they are headed to is actually loaded into
|
|
||||||
// the server
|
|
||||||
_screg.resolveScene(sceneId, rl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is called after the scene to which we are moving is guaranteed
|
|
||||||
* to have been loaded into the server.
|
|
||||||
*/
|
|
||||||
protected void finishMoveToRequest (
|
|
||||||
BodyObject source, SceneManager scmgr, int sceneVersion,
|
|
||||||
SceneMoveListener listener)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
effectSceneMove(source, scmgr, sceneVersion, listener);
|
|
||||||
|
|
||||||
} catch (InvocationException sfe) {
|
|
||||||
listener.requestFailed(sfe.getMessage());
|
|
||||||
|
|
||||||
} catch (RuntimeException re) {
|
|
||||||
Log.logStackTrace(re);
|
|
||||||
listener.requestFailed(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the supplied body into the supplied (already resolved) scene
|
|
||||||
* and informs the supplied listener if the move is successful.
|
|
||||||
*
|
|
||||||
* @exception InvocationException thrown if a failure occurs
|
|
||||||
* attempting to move the user into the place associated with the
|
|
||||||
* scene.
|
|
||||||
*/
|
|
||||||
public void effectSceneMove (BodyObject source, SceneManager scmgr,
|
|
||||||
int sceneVersion, SceneMoveListener listener)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
// move to the place object associated with this scene
|
|
||||||
int ploid = scmgr.getPlaceObject().getOid();
|
|
||||||
PlaceConfig config = _locprov.moveTo(source, ploid);
|
|
||||||
|
|
||||||
// now that we've finally moved, we can update the user object
|
|
||||||
// with the new scene id
|
|
||||||
((ScenedBodyObject)source).setSceneId(scmgr.getScene().getId());
|
|
||||||
|
|
||||||
// check to see if they need a newer version of the scene data
|
|
||||||
SceneModel model = scmgr.getScene().getSceneModel();
|
|
||||||
if (sceneVersion < model.version) {
|
|
||||||
// try getting updates
|
|
||||||
SceneUpdate[] updates = scmgr.getUpdates(sceneVersion);
|
|
||||||
if (updates != null) {
|
|
||||||
listener.moveSucceededWithUpdates(ploid, config, updates);
|
|
||||||
} else {
|
|
||||||
listener.moveSucceededWithScene(ploid, config, model);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
listener.moveSucceeded(ploid, config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ejects the specified body from their current scene and sends them a
|
|
||||||
* request to move to the specified new scene. This is the
|
|
||||||
* scene-equivalent to {@link LocationProvider#moveBody}.
|
|
||||||
*/
|
|
||||||
public void moveBody (BodyObject source, int sceneId)
|
|
||||||
{
|
|
||||||
// first remove them from their old place
|
|
||||||
_locprov.leaveOccupiedPlace(source);
|
|
||||||
|
|
||||||
// then send a forced move notification
|
|
||||||
SceneSender.forcedMove(source, sceneId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ejects the specified body from their current scene and zone. This
|
|
||||||
* is the zone equivalent to {@link
|
|
||||||
* LocationProvider#leaveOccupiedPlace}.
|
|
||||||
*/
|
|
||||||
public void leaveOccupiedScene (ScenedBodyObject source)
|
|
||||||
{
|
|
||||||
// remove them from their occupied place
|
|
||||||
_locprov.leaveOccupiedPlace((BodyObject)source);
|
|
||||||
|
|
||||||
// and clear out their scene information
|
|
||||||
source.setSceneId(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The location provider we use to handle low-level location stuff. */
|
|
||||||
protected LocationProvider _locprov;
|
|
||||||
|
|
||||||
/** The scene registry with which we interact. */
|
|
||||||
protected SceneRegistry _screg;
|
|
||||||
}
|
|
||||||
@@ -1,354 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.server;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.samskivert.util.HashIntMap;
|
|
||||||
import com.samskivert.util.Invoker;
|
|
||||||
|
|
||||||
import com.threerings.presents.server.InvocationManager;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.crowd.server.CrowdServer;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.data.Scene;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.server.persist.SceneRepository;
|
|
||||||
import com.threerings.whirled.util.SceneFactory;
|
|
||||||
import com.threerings.whirled.util.UpdateList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene registry is responsible for the management of all scenes. It
|
|
||||||
* handles interaction with the scene repository and ensures that scenes
|
|
||||||
* are loaded into memory when needed and flushed from memory when not
|
|
||||||
* needed.
|
|
||||||
*
|
|
||||||
* <p> The scene repository also takes care of bridging from the blocking,
|
|
||||||
* synchronous world of the scene repository to the non-blocking
|
|
||||||
* asynchronous world of the distributed object event queue. Thus its
|
|
||||||
* interfaces for accessing scenes are structured so as to not block the
|
|
||||||
* dobjmgr thread while waiting for scenes to be read from or written to
|
|
||||||
* the repository.
|
|
||||||
*
|
|
||||||
* <p><em>Note:</em> All access to the scene registry should take place
|
|
||||||
* from the dobjmgr thread.
|
|
||||||
*/
|
|
||||||
public class SceneRegistry
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Used to create {@link PlaceConfig} instances for scenes.
|
|
||||||
*/
|
|
||||||
public static interface ConfigFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates the place config instance appropriate to the specified
|
|
||||||
* scene.
|
|
||||||
*/
|
|
||||||
PlaceConfig createPlaceConfig (SceneModel model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used to provide scene-related server-side services. */
|
|
||||||
public SceneProvider sceneprov;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a scene registry, instructing it to load and store
|
|
||||||
* scenes using the supplied scene repository.
|
|
||||||
*/
|
|
||||||
public SceneRegistry (InvocationManager invmgr, SceneRepository screp,
|
|
||||||
SceneFactory scfact, ConfigFactory confact)
|
|
||||||
{
|
|
||||||
_screp = screp;
|
|
||||||
_scfact = scfact;
|
|
||||||
_confact = confact;
|
|
||||||
|
|
||||||
// create/register a scene provider with the invocation services
|
|
||||||
sceneprov = new SceneProvider(CrowdServer.plreg.locprov, this);
|
|
||||||
invmgr.registerDispatcher(new SceneDispatcher(sceneprov), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the scene manager assosciated with the specified scene.
|
|
||||||
*
|
|
||||||
* @return the scene manager for the specified scene or null if no
|
|
||||||
* scene manager is loaded for that scene.
|
|
||||||
*/
|
|
||||||
public SceneManager getSceneManager (int sceneId)
|
|
||||||
{
|
|
||||||
return (SceneManager)_scenemgrs.get(sceneId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a reference to the scene repository in use by this
|
|
||||||
* registry.
|
|
||||||
*/
|
|
||||||
public SceneRepository getSceneRepository ()
|
|
||||||
{
|
|
||||||
return _screp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns {@link SceneManager#where} for the specified scene or
|
|
||||||
* <code>null:sceneId</code> if no scene manager exists for that
|
|
||||||
* scene.
|
|
||||||
*/
|
|
||||||
public String where (int sceneId)
|
|
||||||
{
|
|
||||||
SceneManager scmgr = getSceneManager(sceneId);
|
|
||||||
return (scmgr == null) ? ("null:" + sceneId) : scmgr.where();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Because scenes must be loaded from the scene repository and this
|
|
||||||
* must not be done on the dobjmgr thread, the interface for resolving
|
|
||||||
* scenes requires that the entity that wishes for a scene to be
|
|
||||||
* resolved implement this callback interface so that it can be
|
|
||||||
* notified when a scene has been loaded and initialized.
|
|
||||||
*/
|
|
||||||
public static interface ResolutionListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called when the scene has been successfully resolved. The scene
|
|
||||||
* manager instance provided can be used to obtain a reference to
|
|
||||||
* the scene, or the scene distributed object.
|
|
||||||
*/
|
|
||||||
public void sceneWasResolved (SceneManager scmgr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called if some failure occurred in the scene resolution
|
|
||||||
* process.
|
|
||||||
*/
|
|
||||||
public void sceneFailedToResolve (int sceneId, Exception reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the specified scene be resolved, which means loaded
|
|
||||||
* into the server and initialized if the scene is not currently
|
|
||||||
* active. The supplied callback instance will be notified, on the
|
|
||||||
* dobjmgr thread, when the scene has been resolved. If the scene is
|
|
||||||
* already active, it will be notified immediately (before the call to
|
|
||||||
* {@link #resolveScene} returns).
|
|
||||||
*
|
|
||||||
* @param sceneId the id of the scene to resolve.
|
|
||||||
* @param target a reference to a callback instance that will be
|
|
||||||
* notified when the scene has been resolved (which may be immediately
|
|
||||||
* if the scene is already active).
|
|
||||||
*/
|
|
||||||
public void resolveScene (int sceneId, ResolutionListener target)
|
|
||||||
{
|
|
||||||
SceneManager mgr = (SceneManager)_scenemgrs.get(sceneId);
|
|
||||||
if (mgr != null) {
|
|
||||||
// if the scene is already resolved, we're ready to roll
|
|
||||||
target.sceneWasResolved(mgr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Log.debug()) {
|
|
||||||
Log.debug("Resolving scene [id=" + sceneId + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise we've got to resolve the scene and call them back
|
|
||||||
// later; we can manipulate the penders table with impunity here
|
|
||||||
// because we only do so on the dobjmgr thread
|
|
||||||
ArrayList penders = (ArrayList)_penders.get(sceneId);
|
|
||||||
|
|
||||||
// if we're already in the process of resolving this scene, just
|
|
||||||
// add these guys to the list to be notified when it finally is
|
|
||||||
// resolved
|
|
||||||
if (penders != null) {
|
|
||||||
penders.add(target);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// otherwise we've got to initiate the resolution process.
|
|
||||||
// first we create the penders list
|
|
||||||
_penders.put(sceneId, penders = new ArrayList());
|
|
||||||
penders.add(target);
|
|
||||||
|
|
||||||
// i don't like cluttering up method declarations with final
|
|
||||||
// keywords...
|
|
||||||
final int fsceneId = sceneId;
|
|
||||||
|
|
||||||
if (Log.debug()) {
|
|
||||||
Log.debug("Invoking scene lookup [id=" + sceneId + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
// then we queue up an execution unit that'll load the scene
|
|
||||||
// and initialize it and all that
|
|
||||||
WhirledServer.invoker.postUnit(new Invoker.Unit() {
|
|
||||||
// this is run on the invoker thread
|
|
||||||
public boolean invoke ()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
_model = _screp.loadSceneModel(fsceneId);
|
|
||||||
_updates = _screp.loadUpdates(fsceneId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
_cause = e;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is run on the dobjmgr thread
|
|
||||||
public void handleResult ()
|
|
||||||
{
|
|
||||||
if (_model != null) {
|
|
||||||
processSuccessfulResolution(_model, _updates);
|
|
||||||
} else if (_cause != null) {
|
|
||||||
processFailedResolution(fsceneId, _cause);
|
|
||||||
} else {
|
|
||||||
Log.warning("Scene loading unit finished with " +
|
|
||||||
"neither a scene nor a reason for " +
|
|
||||||
"failure!?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return "SceneRegistry.SceneLoader " +
|
|
||||||
(_model == null ? "" : _model.name) +
|
|
||||||
"(" + fsceneId + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SceneModel _model;
|
|
||||||
protected UpdateList _updates;
|
|
||||||
protected Exception _cause;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the scene resolution has completed successfully.
|
|
||||||
*/
|
|
||||||
protected void processSuccessfulResolution (
|
|
||||||
SceneModel model, UpdateList updates)
|
|
||||||
{
|
|
||||||
// now that the scene is loaded, we can create a scene manager for
|
|
||||||
// it. that will be initialized by the place registry and when
|
|
||||||
// that is finally complete, then we can let our penders know
|
|
||||||
// what's up
|
|
||||||
|
|
||||||
try {
|
|
||||||
// first create our scene instance
|
|
||||||
Scene scene = _scfact.createScene(
|
|
||||||
model, _confact.createPlaceConfig(model));
|
|
||||||
|
|
||||||
// now create our scene manager
|
|
||||||
SceneManager scmgr = (SceneManager)
|
|
||||||
CrowdServer.plreg.createPlace(scene.getPlaceConfig(), null);
|
|
||||||
scmgr.setSceneData(scene, updates, this);
|
|
||||||
|
|
||||||
// when the scene manager completes its startup procedings, it
|
|
||||||
// will call back to the scene registry and let us know that
|
|
||||||
// we can turn the penders loose
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
// so close, but no cigar
|
|
||||||
processFailedResolution(model.sceneId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called if resolving the scene fails for some reason.
|
|
||||||
*/
|
|
||||||
protected void processFailedResolution (int sceneId, Exception cause)
|
|
||||||
{
|
|
||||||
Log.info("Failed to resolve scene [sceneId=" + sceneId +
|
|
||||||
", cause=" + cause + "].");
|
|
||||||
Log.logStackTrace(cause);
|
|
||||||
|
|
||||||
// alas things didn't work out, notify our penders
|
|
||||||
ArrayList penders = (ArrayList)_penders.remove(sceneId);
|
|
||||||
if (penders != null) {
|
|
||||||
for (int i = 0; i < penders.size(); i++) {
|
|
||||||
ResolutionListener rl = (ResolutionListener)penders.get(i);
|
|
||||||
try {
|
|
||||||
rl.sceneFailedToResolve(sceneId, cause);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.warning("Resolution listener choked.");
|
|
||||||
Log.logStackTrace(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the scene manager once it has started up (meaning that it
|
|
||||||
* has its place object and is ready to roll).
|
|
||||||
*/
|
|
||||||
protected void sceneManagerDidStart (SceneManager scmgr)
|
|
||||||
{
|
|
||||||
// register this scene manager in our table
|
|
||||||
int sceneId = scmgr.getScene().getId();
|
|
||||||
_scenemgrs.put(sceneId, scmgr);
|
|
||||||
|
|
||||||
if (Log.debug()) {
|
|
||||||
Log.debug("Registering scene manager [scid=" + sceneId +
|
|
||||||
", scmgr=" + scmgr + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
// now notify any penders
|
|
||||||
ArrayList penders = (ArrayList)_penders.remove(sceneId);
|
|
||||||
if (penders != null) {
|
|
||||||
for (int i = 0; i < penders.size(); i++) {
|
|
||||||
ResolutionListener rl = (ResolutionListener)penders.get(i);
|
|
||||||
try {
|
|
||||||
rl.sceneWasResolved(scmgr);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.warning("Resolution listener choked.");
|
|
||||||
Log.logStackTrace(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the scene manager when it is shut down.
|
|
||||||
*/
|
|
||||||
protected void unmapSceneManager (SceneManager scmgr)
|
|
||||||
{
|
|
||||||
if (_scenemgrs.remove(scmgr.getScene().getId()) == null) {
|
|
||||||
Log.warning("Requested to unmap unmapped scene manager " +
|
|
||||||
"[scmgr=" + scmgr + "].");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Log.debug()) {
|
|
||||||
Log.debug("Unmapped scene manager " + scmgr + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The entity from which we load scene models. */
|
|
||||||
protected SceneRepository _screp;
|
|
||||||
|
|
||||||
/** Used to generate place configs for our scenes. */
|
|
||||||
protected ConfigFactory _confact;
|
|
||||||
|
|
||||||
/** The entity via which we create scene instances from scene
|
|
||||||
* models. */
|
|
||||||
protected SceneFactory _scfact;
|
|
||||||
|
|
||||||
/** A mapping from scene ids to scene managers. */
|
|
||||||
protected HashIntMap _scenemgrs = new HashIntMap();
|
|
||||||
|
|
||||||
/** The table of pending resolution listeners. */
|
|
||||||
protected HashIntMap _penders = new HashIntMap();
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.server;
|
|
||||||
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.server.InvocationSender;
|
|
||||||
import com.threerings.whirled.client.SceneDecoder;
|
|
||||||
import com.threerings.whirled.client.SceneReceiver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to issue notifications to a {@link SceneReceiver} instance on a
|
|
||||||
* client.
|
|
||||||
*/
|
|
||||||
public class SceneSender extends InvocationSender
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Issues a notification that will result in a call to {@link
|
|
||||||
* SceneReceiver#forcedMove} on a client.
|
|
||||||
*/
|
|
||||||
public static void forcedMove (
|
|
||||||
ClientObject target, int arg1)
|
|
||||||
{
|
|
||||||
sendNotification(
|
|
||||||
target, SceneDecoder.RECEIVER_CODE, SceneDecoder.FORCED_MOVE,
|
|
||||||
new Object[] { Integer.valueOf(arg1) });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.server;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.BodyObject;
|
|
||||||
import com.threerings.crowd.server.CrowdClient;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.ScenedBodyObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The client object used by client management on the Whirled server.
|
|
||||||
*/
|
|
||||||
public class WhirledClient extends CrowdClient
|
|
||||||
{
|
|
||||||
// documentation inherited from interface
|
|
||||||
protected void clearLocation (BodyObject bobj)
|
|
||||||
{
|
|
||||||
WhirledServer.screg.sceneprov.leaveOccupiedScene(
|
|
||||||
(ScenedBodyObject)bobj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.server;
|
|
||||||
|
|
||||||
import com.threerings.crowd.server.CrowdServer;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.server.persist.SceneRepository;
|
|
||||||
import com.threerings.whirled.util.SceneFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The whirled server extends the {@link CrowdServer} and provides access
|
|
||||||
* to managers and the like that are needed by the Whirled serviecs.
|
|
||||||
*/
|
|
||||||
public abstract class WhirledServer extends CrowdServer
|
|
||||||
{
|
|
||||||
/** The scene registry. */
|
|
||||||
public static SceneRegistry screg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes all of the server services and prepares for operation.
|
|
||||||
*/
|
|
||||||
public void init ()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
// do the base server initialization
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
// configure the client to use our whirled client
|
|
||||||
clmgr.setClientClass(WhirledClient.class);
|
|
||||||
|
|
||||||
// create the scene repository
|
|
||||||
_screp = createSceneRepository();
|
|
||||||
|
|
||||||
// create our scene registry
|
|
||||||
screg = new SceneRegistry(invmgr, _screp, createSceneFactory(),
|
|
||||||
createConfigFactory());
|
|
||||||
|
|
||||||
Log.info("Whirled server initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the scene repository that will be used by this server.
|
|
||||||
*
|
|
||||||
* @exception Exception thrown if any error occurs while instantiating
|
|
||||||
* or initializing the scene repository.
|
|
||||||
*/
|
|
||||||
protected abstract SceneRepository createSceneRepository ()
|
|
||||||
throws Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the scene factory that will be used by our scene registry.
|
|
||||||
*
|
|
||||||
* @exception Exception thrown if any error occurs while instantiating
|
|
||||||
* or initializing the scene repository.
|
|
||||||
*/
|
|
||||||
protected abstract SceneFactory createSceneFactory ()
|
|
||||||
throws Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the place config factory that will be used our scene
|
|
||||||
* registry.
|
|
||||||
*
|
|
||||||
* @exception Exception thrown if any error occurs while instantiating
|
|
||||||
* or initializing the scene repository.
|
|
||||||
*/
|
|
||||||
protected abstract SceneRegistry.ConfigFactory createConfigFactory ()
|
|
||||||
throws Exception;
|
|
||||||
|
|
||||||
/** The scene repository in use by this server. */
|
|
||||||
protected SceneRepository _screp;
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.server.persist;
|
|
||||||
|
|
||||||
import com.samskivert.io.PersistenceException;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.util.NoSuchSceneException;
|
|
||||||
import com.threerings.whirled.util.UpdateList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The dummy scene repository just pretends to load and store scenes, but
|
|
||||||
* in fact it just creates new blank scenes when requested to load a scene
|
|
||||||
* and does nothing when requested to save one.
|
|
||||||
*/
|
|
||||||
public class DummySceneRepository implements SceneRepository
|
|
||||||
{
|
|
||||||
// documentation inherited
|
|
||||||
public SceneModel loadSceneModel (int sceneId)
|
|
||||||
throws PersistenceException, NoSuchSceneException
|
|
||||||
{
|
|
||||||
Log.info("Creating dummy scene [id=" + sceneId + "].");
|
|
||||||
return SceneModel.blankSceneModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public UpdateList loadUpdates (int sceneId)
|
|
||||||
throws PersistenceException, NoSuchSceneException
|
|
||||||
{
|
|
||||||
return new UpdateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void applyAndRecordUpdate (SceneModel model, SceneUpdate update)
|
|
||||||
throws PersistenceException
|
|
||||||
{
|
|
||||||
// nothing doing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.server.persist;
|
|
||||||
|
|
||||||
import com.samskivert.io.PersistenceException;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.util.NoSuchSceneException;
|
|
||||||
import com.threerings.whirled.util.UpdateList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene repository provides the basic interface for loading and
|
|
||||||
* updating scene data. It is used by the scene registry and though more
|
|
||||||
* scene related persistence services may be needed in a full-fledged
|
|
||||||
* application, the scene repository only encapsulates those needed by the
|
|
||||||
* scene registry and other services provided by the Whirled framework.
|
|
||||||
*/
|
|
||||||
public interface SceneRepository
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Fetches the model for the scene with the specified scene id.
|
|
||||||
*
|
|
||||||
* @exception PersistenceException thrown if an error occurs
|
|
||||||
* attempting to load the scene data.
|
|
||||||
* @exception NoSuchSceneException thrown if no scene exists with the
|
|
||||||
* specified scene id.
|
|
||||||
*/
|
|
||||||
public SceneModel loadSceneModel (int sceneId)
|
|
||||||
throws PersistenceException, NoSuchSceneException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the set of updates associated with the specified scene.
|
|
||||||
*
|
|
||||||
* @exception PersistenceException thrown if an error occurs
|
|
||||||
* attempting to load the scene updates.
|
|
||||||
* @exception NoSuchSceneException thrown if no scene exists with the
|
|
||||||
* specified scene id.
|
|
||||||
*/
|
|
||||||
public UpdateList loadUpdates (int sceneId)
|
|
||||||
throws PersistenceException, NoSuchSceneException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applise the supplied scene update to persistent representation of
|
|
||||||
* its associated scene, then stores the update persistently for
|
|
||||||
* future invocations of the server to load. <em>Note:</em> the scene
|
|
||||||
* update will have already been applied to the supplied scene model.
|
|
||||||
*
|
|
||||||
* @exception PersistenceException thrown if an error occurs
|
|
||||||
* attempting to apply the scene update.
|
|
||||||
*/
|
|
||||||
public void applyAndRecordUpdate (SceneModel model, SceneUpdate update)
|
|
||||||
throws PersistenceException;
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder class that contains a reference to the log object used by
|
|
||||||
* the Whirled Spot services.
|
|
||||||
*/
|
|
||||||
public class Log
|
|
||||||
{
|
|
||||||
public static com.samskivert.util.Log log =
|
|
||||||
new com.samskivert.util.Log("whirled.spot");
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void debug (String message)
|
|
||||||
{
|
|
||||||
log.debug(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void info (String message)
|
|
||||||
{
|
|
||||||
log.info(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void warning (String message)
|
|
||||||
{
|
|
||||||
log.warning(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void logStackTrace (Throwable t)
|
|
||||||
{
|
|
||||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.client;
|
|
||||||
|
|
||||||
import com.threerings.whirled.client.SceneController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base spot scene controller class. It is expected that users of the
|
|
||||||
* Whirled Spot services will extend this controller class when creating
|
|
||||||
* specialized controllers for their scenes. Presently there are no basic
|
|
||||||
* scene services provided by this controller, but its existence affords
|
|
||||||
* the addition of such services should they become necessary in the
|
|
||||||
* future.
|
|
||||||
*/
|
|
||||||
public abstract class SpotSceneController extends SceneController
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,492 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.client;
|
|
||||||
|
|
||||||
import com.samskivert.util.ResultListener;
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.BasicDirector;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.client.InvocationService.ConfirmListener;
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
|
||||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
|
||||||
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.crowd.chat.client.ChatDirector;
|
|
||||||
import com.threerings.crowd.chat.data.ChatCodes;
|
|
||||||
import com.threerings.crowd.client.LocationAdapter;
|
|
||||||
import com.threerings.crowd.client.LocationDirector;
|
|
||||||
import com.threerings.crowd.data.PlaceObject;
|
|
||||||
|
|
||||||
import com.threerings.whirled.client.SceneDirector;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.ScenedBodyObject;
|
|
||||||
import com.threerings.whirled.util.WhirledContext;
|
|
||||||
|
|
||||||
import com.threerings.whirled.spot.Log;
|
|
||||||
import com.threerings.whirled.spot.data.ClusteredBodyObject;
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
import com.threerings.whirled.spot.data.Portal;
|
|
||||||
import com.threerings.whirled.spot.data.SpotCodes;
|
|
||||||
import com.threerings.whirled.spot.data.SpotScene;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extends the standard scene director with facilities to move between
|
|
||||||
* locations within a scene.
|
|
||||||
*/
|
|
||||||
public class SpotSceneDirector extends BasicDirector
|
|
||||||
implements SpotCodes, Subscriber, AttributeChangeListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a new spot scene director with the specified context and
|
|
||||||
* which will cooperate with the supplied scene director.
|
|
||||||
*
|
|
||||||
* @param ctx the active client context.
|
|
||||||
* @param locdir the location director with which we will be
|
|
||||||
* cooperating.
|
|
||||||
* @param scdir the scene director with which we will be cooperating.
|
|
||||||
*/
|
|
||||||
public SpotSceneDirector (WhirledContext ctx, LocationDirector locdir,
|
|
||||||
SceneDirector scdir)
|
|
||||||
{
|
|
||||||
super(ctx);
|
|
||||||
|
|
||||||
_ctx = ctx;
|
|
||||||
_scdir = scdir;
|
|
||||||
|
|
||||||
// wire ourselves up to hear about leave place notifications
|
|
||||||
locdir.addLocationObserver(new LocationAdapter() {
|
|
||||||
public void locationDidChange (PlaceObject place) {
|
|
||||||
// we need to clear some things out when we leave a place
|
|
||||||
handleDeparture();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures this spot scene director with a chat director, with
|
|
||||||
* which it will coordinate to implement cluster chatting.
|
|
||||||
*/
|
|
||||||
public void setChatDirector (ChatDirector chatdir)
|
|
||||||
{
|
|
||||||
_chatdir = chatdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns our current location unless we have a location change
|
|
||||||
* pending, in which case our pending location is returned.
|
|
||||||
*/
|
|
||||||
public Location getIntendedLocation ()
|
|
||||||
{
|
|
||||||
return (_pendingLoc != null) ? _pendingLoc : _location;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that this client move to the location specified by the
|
|
||||||
* supplied portal id. A request will be made and when the response is
|
|
||||||
* received, the location observers will be notified of success or
|
|
||||||
* failure.
|
|
||||||
*
|
|
||||||
* @return true if the request was issued, false if it was rejected by
|
|
||||||
* a location observer or because we have another request outstanding.
|
|
||||||
*/
|
|
||||||
public boolean traversePortal (int portalId)
|
|
||||||
{
|
|
||||||
return traversePortal(portalId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that this client move to the location specified by the
|
|
||||||
* supplied portal id. A request will be made and when the response is
|
|
||||||
* received, the location observers will be notified of success or
|
|
||||||
* failure.
|
|
||||||
*/
|
|
||||||
public boolean traversePortal (int portalId, ResultListener rl)
|
|
||||||
{
|
|
||||||
// look up the destination scene and location
|
|
||||||
SpotScene scene = (SpotScene)_scdir.getScene();
|
|
||||||
if (scene == null) {
|
|
||||||
Log.warning("Requested to traverse portal when we have " +
|
|
||||||
"no scene [portalId=" + portalId + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanity check the server's notion of what scene we're in with
|
|
||||||
// our notion of it
|
|
||||||
int sceneId = _scdir.getScene().getId();
|
|
||||||
ScenedBodyObject sbobj = (ScenedBodyObject)
|
|
||||||
_ctx.getClient().getClientObject();
|
|
||||||
if (sceneId != sbobj.getSceneId()) {
|
|
||||||
Log.warning("Client and server differ in opinion of what scene " +
|
|
||||||
"we're in [sSceneId=" + sbobj.getSceneId() +
|
|
||||||
", cSceneId=" + sceneId + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the portal they're talking about
|
|
||||||
Portal dest = scene.getPortal(portalId);
|
|
||||||
if (dest == null) {
|
|
||||||
Log.warning("Requested to traverse non-existent portal " +
|
|
||||||
"[portalId=" + portalId + ", portals=" +
|
|
||||||
StringUtil.toString(scene.getPortals()) + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare to move to this scene (sets up pending data)
|
|
||||||
if (!_scdir.prepareMoveTo(dest.targetSceneId, rl)) {
|
|
||||||
Log.info("Portal traversal vetoed by scene director " +
|
|
||||||
"[portalId=" + portalId + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the version of our cached copy of the scene to which
|
|
||||||
// we're requesting to move; if we were unable to load it, assume
|
|
||||||
// a cached version of zero
|
|
||||||
int sceneVer = 0;
|
|
||||||
SceneModel pendingModel = _scdir.getPendingModel();
|
|
||||||
if (pendingModel != null) {
|
|
||||||
sceneVer = pendingModel.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// issue a traversePortal request
|
|
||||||
Log.info("Issuing traversePortal(" +
|
|
||||||
sceneId + ", " + dest + ", " + sceneVer + ").");
|
|
||||||
_sservice.traversePortal(
|
|
||||||
_ctx.getClient(), sceneId, portalId, sceneVer, _scdir);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Issues a request to change our location within the scene to the
|
|
||||||
* specified location.
|
|
||||||
*
|
|
||||||
* @param loc the new location to which to move.
|
|
||||||
* @param listener will be notified of success or failure. Most client
|
|
||||||
* entities find out about location changes via changes to the
|
|
||||||
* occupant info data, but the initiator of a location change request
|
|
||||||
* can be notified of its success or failure, primarily so that it can
|
|
||||||
* act in anticipation of a successful location change (like by
|
|
||||||
* starting a sprite moving toward the new location), but backtrack if
|
|
||||||
* it finds out that the location change failed.
|
|
||||||
*/
|
|
||||||
public void changeLocation (Location loc, final ResultListener listener)
|
|
||||||
{
|
|
||||||
// refuse if there's a pending location change or if we're already
|
|
||||||
// at the specified location
|
|
||||||
if (loc.equivalent(_location)) {
|
|
||||||
Log.info("Not going to " + loc + "; we're at " + _location +
|
|
||||||
" and we're headed to " + _pendingLoc + ".");
|
|
||||||
if (listener != null) {
|
|
||||||
// This isn't really a failure, it's just a no-op.
|
|
||||||
listener.requestCompleted(_location);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pendingLoc != null) {
|
|
||||||
Log.info("Not going to " + loc + "; we're at " + _location +
|
|
||||||
" and we're headed to " + _pendingLoc + ".");
|
|
||||||
if (listener != null) {
|
|
||||||
// Already moving, best thing to do is ignore it.
|
|
||||||
listener.requestCompleted(_pendingLoc);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpotScene scene = (SpotScene)_scdir.getScene();
|
|
||||||
if (scene == null) {
|
|
||||||
Log.warning("Requested to change locations, but we're not " +
|
|
||||||
"currently in any scene [loc=" + loc + "].");
|
|
||||||
if (listener != null) {
|
|
||||||
listener.requestFailed(new Exception("m.cant_get_there"));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sceneId = _scdir.getScene().getId();
|
|
||||||
Log.info("Sending changeLocation request [scid=" + sceneId +
|
|
||||||
", loc=" + loc + "].");
|
|
||||||
|
|
||||||
_pendingLoc = (Location)loc.clone();
|
|
||||||
ConfirmListener clist = new ConfirmListener() {
|
|
||||||
public void requestProcessed () {
|
|
||||||
_location = _pendingLoc;
|
|
||||||
_pendingLoc = null;
|
|
||||||
if (listener != null) {
|
|
||||||
listener.requestCompleted(_location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestFailed (String reason) {
|
|
||||||
_pendingLoc = null;
|
|
||||||
if (listener != null) {
|
|
||||||
listener.requestFailed(new Exception(reason));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_sservice.changeLocation(_ctx.getClient(), sceneId, loc, clist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Issues a request to join the cluster associated with the specified
|
|
||||||
* user (starting one if necessary).
|
|
||||||
*
|
|
||||||
* @param froid the bodyOid of another user; the calling user will
|
|
||||||
* be made to join the target user's cluster.
|
|
||||||
* @param listener will be notified of success or failure.
|
|
||||||
*/
|
|
||||||
public void joinCluster (int froid, final ResultListener listener)
|
|
||||||
{
|
|
||||||
SpotScene scene = (SpotScene)_scdir.getScene();
|
|
||||||
if (scene == null) {
|
|
||||||
Log.warning("Requested to join cluster, but we're not " +
|
|
||||||
"currently in any scene [froid=" + froid + "].");
|
|
||||||
if (listener != null) {
|
|
||||||
listener.requestFailed(new Exception("m.cant_get_there"));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.info("Joining cluster [friend=" + froid + "].");
|
|
||||||
|
|
||||||
_sservice.joinCluster(_ctx.getClient(), froid, new ConfirmListener() {
|
|
||||||
public void requestProcessed () {
|
|
||||||
if (listener != null) {
|
|
||||||
listener.requestCompleted(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestFailed (String reason) {
|
|
||||||
if (listener != null) {
|
|
||||||
listener.requestFailed(new Exception(reason));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a chat message to the other users in the cluster to which the
|
|
||||||
* location that we currently occupy belongs.
|
|
||||||
*
|
|
||||||
* @return true if a cluster speak message was delivered, false if we
|
|
||||||
* are not in a valid cluster and refused to deliver the request.
|
|
||||||
*/
|
|
||||||
public boolean requestClusterSpeak (String message)
|
|
||||||
{
|
|
||||||
return requestClusterSpeak(message, ChatCodes.DEFAULT_MODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a chat message to the other users in the cluster to which the
|
|
||||||
* location that we currently occupy belongs.
|
|
||||||
*
|
|
||||||
* @return true if a cluster speak message was delivered, false if we
|
|
||||||
* are not in a valid cluster and refused to deliver the request.
|
|
||||||
*/
|
|
||||||
public boolean requestClusterSpeak (String message, byte mode)
|
|
||||||
{
|
|
||||||
// make sure we're currently in a scene
|
|
||||||
SpotScene scene = (SpotScene)_scdir.getScene();
|
|
||||||
if (scene == null) {
|
|
||||||
Log.warning("Requested to speak to cluster, but we're not " +
|
|
||||||
"currently in any scene [message=" + message + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we're part of a cluster
|
|
||||||
if (_self.getClusterOid() <= 0) {
|
|
||||||
Log.info("Ignoring cluster speak as we're not in a cluster " +
|
|
||||||
"[cloid=" + _self.getClusterOid() + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
message = _chatdir.filter(message, null, true);
|
|
||||||
if (message != null) {
|
|
||||||
_sservice.clusterSpeak(_ctx.getClient(), message, mode);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void objectAvailable (DObject object)
|
|
||||||
{
|
|
||||||
clearCluster(false);
|
|
||||||
int oid = object.getOid();
|
|
||||||
if (oid != _self.getClusterOid()) {
|
|
||||||
// we got it too late, just unsubscribe
|
|
||||||
DObjectManager omgr = _ctx.getDObjectManager();
|
|
||||||
omgr.unsubscribeFromObject(oid, this);
|
|
||||||
} else {
|
|
||||||
// it's our new cluster!
|
|
||||||
_clobj = object;
|
|
||||||
if (_chatdir != null) {
|
|
||||||
_chatdir.addAuxiliarySource(object, CLUSTER_CHAT_TYPE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void requestFailed (int oid, ObjectAccessException cause)
|
|
||||||
{
|
|
||||||
Log.warning("Unable to subscribe to cluster chat object " +
|
|
||||||
"[oid=" + oid + ", cause=" + cause + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void attributeChanged (AttributeChangedEvent event)
|
|
||||||
{
|
|
||||||
if (event.getName().equals(_self.getClusterField()) &&
|
|
||||||
!event.getValue().equals(event.getOldValue())) {
|
|
||||||
maybeUpdateCluster();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void clientDidLogon (Client client)
|
|
||||||
{
|
|
||||||
super.clientDidLogon(client);
|
|
||||||
|
|
||||||
ClientObject clientObj = client.getClientObject();
|
|
||||||
if (clientObj instanceof ClusteredBodyObject) {
|
|
||||||
// listen to the client object
|
|
||||||
clientObj.addListener(this);
|
|
||||||
_self = (ClusteredBodyObject) clientObj;
|
|
||||||
|
|
||||||
// we may need to subscribe to a cluster due to session resumption
|
|
||||||
maybeUpdateCluster();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void clientObjectDidChange (Client client)
|
|
||||||
{
|
|
||||||
super.clientObjectDidChange(client);
|
|
||||||
|
|
||||||
// listen to the client object
|
|
||||||
ClientObject clientObj = client.getClientObject();
|
|
||||||
clientObj.addListener(this);
|
|
||||||
_self = (ClusteredBodyObject) clientObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void clientDidLogoff (Client client)
|
|
||||||
{
|
|
||||||
super.clientDidLogoff(client);
|
|
||||||
|
|
||||||
// clear out our business
|
|
||||||
_location = null;
|
|
||||||
_pendingLoc = null;
|
|
||||||
_sservice = null;
|
|
||||||
clearCluster(true);
|
|
||||||
|
|
||||||
// stop listening to the client object
|
|
||||||
client.getClientObject().removeListener(this);
|
|
||||||
_self = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void fetchServices (Client client)
|
|
||||||
{
|
|
||||||
_sservice = (SpotService)client.requireService(SpotService.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up after a few things when we depart from a scene.
|
|
||||||
*/
|
|
||||||
protected void handleDeparture ()
|
|
||||||
{
|
|
||||||
// clear out our last known location id
|
|
||||||
_location = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks to see if our cluster has changed and does the necessary
|
|
||||||
* subscription machinations if necessary.
|
|
||||||
*/
|
|
||||||
protected void maybeUpdateCluster ()
|
|
||||||
{
|
|
||||||
int cloid = _self.getClusterOid();
|
|
||||||
if ((_clobj == null && cloid <= 0) ||
|
|
||||||
(_clobj != null && cloid == _clobj.getOid())) {
|
|
||||||
// our cluster didn't change, we can stop now
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear out any old cluster object
|
|
||||||
clearCluster(false);
|
|
||||||
|
|
||||||
// if there's a new cluster object, subscribe to it
|
|
||||||
if (_chatdir != null && cloid > 0) {
|
|
||||||
DObjectManager omgr = _ctx.getDObjectManager();
|
|
||||||
// we'll wire up to the chat director when this completes
|
|
||||||
omgr.subscribeToObject(cloid, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience routine to unwire chat for and unsubscribe from our
|
|
||||||
* current cluster, if any.
|
|
||||||
*
|
|
||||||
* @param force clear the cluster even if we're still apparently in it.
|
|
||||||
*/
|
|
||||||
protected void clearCluster (boolean force)
|
|
||||||
{
|
|
||||||
if (_clobj != null &&
|
|
||||||
(force || (_clobj.getOid() != _self.getClusterOid()))) {
|
|
||||||
if (_chatdir != null) {
|
|
||||||
_chatdir.removeAuxiliarySource(_clobj);
|
|
||||||
}
|
|
||||||
DObjectManager omgr = _ctx.getDObjectManager();
|
|
||||||
omgr.unsubscribeFromObject(_clobj.getOid(), this);
|
|
||||||
_clobj = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The active client context. */
|
|
||||||
protected WhirledContext _ctx;
|
|
||||||
|
|
||||||
/** Access to spot scene services. */
|
|
||||||
protected SpotService _sservice;
|
|
||||||
|
|
||||||
/** The scene director with which we are cooperating. */
|
|
||||||
protected SceneDirector _scdir;
|
|
||||||
|
|
||||||
/** A casted reference to our clustered body object. */
|
|
||||||
protected ClusteredBodyObject _self;
|
|
||||||
|
|
||||||
/** A reference to the chat director with which we coordinate. */
|
|
||||||
protected ChatDirector _chatdir;
|
|
||||||
|
|
||||||
/** The location we currently occupy. */
|
|
||||||
protected Location _location;
|
|
||||||
|
|
||||||
/** The location to which we have an outstanding change location
|
|
||||||
* request. */
|
|
||||||
protected Location _pendingLoc;
|
|
||||||
|
|
||||||
/** The cluster chat object for the cluster we currently occupy. */
|
|
||||||
protected DObject _clobj;
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.client.InvocationService;
|
|
||||||
|
|
||||||
import com.threerings.whirled.client.SceneService.SceneMoveListener;
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the mechanism by which the client can request to move around
|
|
||||||
* within a scene and between scenes (taking exit and entry locations into
|
|
||||||
* account). These services should not be used directly, but instead
|
|
||||||
* should be accessed via the {@link SpotSceneDirector}.
|
|
||||||
*/
|
|
||||||
public interface SpotService extends InvocationService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Requests to traverse the specified portal.
|
|
||||||
*
|
|
||||||
* @param sceneId the player's current scene which is used to sanity
|
|
||||||
* check things when the request actually arrives.
|
|
||||||
* @param portalId the portal to be traversed.
|
|
||||||
* @param destSceneVer the version of the destination scene data that
|
|
||||||
* the client has in its local repository.
|
|
||||||
*/
|
|
||||||
public void traversePortal (
|
|
||||||
Client client, int sceneId, int portalId, int destSceneVer,
|
|
||||||
SceneMoveListener listener);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that this client's body be made to move to the specified
|
|
||||||
* location. The user will be removed from any cluster from which they
|
|
||||||
* are an occupant.
|
|
||||||
*
|
|
||||||
* @param sceneId the id of the scene in which to change location.
|
|
||||||
* @param loc the location to which to move.
|
|
||||||
*/
|
|
||||||
public void changeLocation (Client client, int sceneId, Location loc,
|
|
||||||
ConfirmListener listener);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that this client start or join the specified cluster. They
|
|
||||||
* will be relocated appropriately by the scene manager.
|
|
||||||
*
|
|
||||||
* @param friendOid the bodyOid of another user or the oid of an
|
|
||||||
* existing cluster; the calling user will be made to join the cluster
|
|
||||||
* or target user's cluster, or create a cluster with the target user
|
|
||||||
* if they are not already in one.
|
|
||||||
*/
|
|
||||||
public void joinCluster (Client client, int friendOid,
|
|
||||||
ConfirmListener listener);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the supplied message be delivered to listeners in the
|
|
||||||
* cluster to which the specified location belongs.
|
|
||||||
*
|
|
||||||
* @param message the text of the message to be spoken.
|
|
||||||
* @param mode an associated mode constant that can be used to
|
|
||||||
* identify different kinds of "speech" (emote, thought bubble, etc.).
|
|
||||||
*/
|
|
||||||
public void clusterSpeak (Client client, String message, byte mode);
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import java.awt.Rectangle;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.threerings.io.Streamable;
|
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains information on clusters.
|
|
||||||
*/
|
|
||||||
public class Cluster extends Rectangle
|
|
||||||
implements DSet.Entry, Streamable
|
|
||||||
{
|
|
||||||
/** A unique identifier for this cluster (also the distributed object
|
|
||||||
* id of the cluster chat object). */
|
|
||||||
public int clusterOid;
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public Comparable getKey ()
|
|
||||||
{
|
|
||||||
if (_key == null) {
|
|
||||||
_key = Integer.valueOf(clusterOid);
|
|
||||||
}
|
|
||||||
return _key;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public boolean equals (Object other)
|
|
||||||
{
|
|
||||||
if (other instanceof Cluster) {
|
|
||||||
return ((Cluster)other).clusterOid == clusterOid;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public int hashCode ()
|
|
||||||
{
|
|
||||||
return clusterOid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a string representation of this instance.
|
|
||||||
*/
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return StringUtil.fieldsToString(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used for {@link #getKey}. */
|
|
||||||
protected transient Integer _key;
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DObject;
|
|
||||||
import com.threerings.presents.dobj.OidList;
|
|
||||||
|
|
||||||
import com.threerings.crowd.chat.data.SpeakObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to dispatch chat in clusters.
|
|
||||||
*/
|
|
||||||
public class ClusterObject extends DObject
|
|
||||||
implements SpeakObject
|
|
||||||
{
|
|
||||||
// AUTO-GENERATED: FIELDS START
|
|
||||||
/** The field name of the <code>occupants</code> field. */
|
|
||||||
public static final String OCCUPANTS = "occupants";
|
|
||||||
// AUTO-GENERATED: FIELDS END
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks the oid of the body objects that occupy this cluster.
|
|
||||||
*/
|
|
||||||
public OidList occupants = new OidList();
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void applyToListeners (ListenerOp op)
|
|
||||||
{
|
|
||||||
for (int ii = 0, ll = occupants.size(); ii < ll; ii++) {
|
|
||||||
op.apply(occupants.get(ii));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AUTO-GENERATED: METHODS START
|
|
||||||
/**
|
|
||||||
* Requests that <code>oid</code> be added to the <code>occupants</code>
|
|
||||||
* oid list. The list will not change until the event is actually
|
|
||||||
* propagated through the system.
|
|
||||||
*/
|
|
||||||
public void addToOccupants (int oid)
|
|
||||||
{
|
|
||||||
requestOidAdd(OCCUPANTS, oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that <code>oid</code> be removed from the
|
|
||||||
* <code>occupants</code> oid list. The list will not change until the
|
|
||||||
* event is actually propagated through the system.
|
|
||||||
*/
|
|
||||||
public void removeFromOccupants (int oid)
|
|
||||||
{
|
|
||||||
requestOidRemove(OCCUPANTS, oid);
|
|
||||||
}
|
|
||||||
// AUTO-GENERATED: METHODS END
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.ScenedBodyObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines some required methods for a {@link ScenedBodyObject} that is to
|
|
||||||
* participate in the Whirled Spot system.
|
|
||||||
*/
|
|
||||||
public interface ClusteredBodyObject extends ScenedBodyObject
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns the field name of the cluster oid distributed object field.
|
|
||||||
*/
|
|
||||||
public String getClusterField ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the oid of the cluster to which this user currently
|
|
||||||
* belongs.
|
|
||||||
*/
|
|
||||||
public int getClusterOid ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the oid of the cluster to which this user currently belongs.
|
|
||||||
*/
|
|
||||||
public void setClusterOid (int clusterOid);
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package com.threerings.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.io.Streamable;
|
|
||||||
|
|
||||||
public interface Location extends Streamable, Cloneable
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get a new Location instance that is equals() to this one but that
|
|
||||||
* has an orientation facing the opposite direction.
|
|
||||||
*/
|
|
||||||
public Location getOpposite ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two locations are equivalent if they specify the same location
|
|
||||||
* and orientation.
|
|
||||||
*/
|
|
||||||
public boolean equivalent (Location other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two locations are equals if they specify the same coordinates, but
|
|
||||||
* the orientation may be different.
|
|
||||||
*/
|
|
||||||
public boolean equals (Object other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The hashcode of a Location should be based only on its coordinates.
|
|
||||||
*/
|
|
||||||
public int hashCode ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locations are cloneable.
|
|
||||||
*/
|
|
||||||
public Object clone ();
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.io.SimpleStreamableObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an exit to another scene. A body sprite would walk over to a
|
|
||||||
* portal's coordinates and then either proceed off of the edge of the
|
|
||||||
* display, or open a door and walk through it, or fizzle away in a Star
|
|
||||||
* Trekkian transporter style or whatever is appropriate for the game in
|
|
||||||
* question. It contains information on the scene to which the body exits
|
|
||||||
* when using this portal and the location at which the body sprite should
|
|
||||||
* appear in that target scene.
|
|
||||||
*/
|
|
||||||
public class Portal extends SimpleStreamableObject
|
|
||||||
implements Cloneable
|
|
||||||
{
|
|
||||||
/** This portal's unique identifier. */
|
|
||||||
public short portalId;
|
|
||||||
|
|
||||||
/** The location of the portal.
|
|
||||||
* This field is present on client and server, it is streamed specially. */
|
|
||||||
public Location loc;
|
|
||||||
|
|
||||||
/** The scene identifier of the scene to which a body will exit when
|
|
||||||
* they "use" this portal. */
|
|
||||||
public int targetSceneId;
|
|
||||||
|
|
||||||
/** The portal identifier of the portal at which a body will enter
|
|
||||||
* the target scene when they "use" this portal. */
|
|
||||||
public short targetPortalId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a location instance configured with the location and
|
|
||||||
* orientation of this portal.
|
|
||||||
*/
|
|
||||||
public Location getLocation ()
|
|
||||||
{
|
|
||||||
return (Location) loc.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a location instance configured with the location and
|
|
||||||
* opposite orientation of this portal. This is useful for when a body
|
|
||||||
* is entering a scene at a portal and we want them to face the
|
|
||||||
* opposite direction (as they are entering via the portal rather than
|
|
||||||
* leaving, which is the natural "orientation" of a portal).
|
|
||||||
*/
|
|
||||||
public Location getOppLocation ()
|
|
||||||
{
|
|
||||||
return loc.getOpposite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the portal has a potentially valid target scene and
|
|
||||||
* portal id (they are not guaranteed to exist, but they are at least
|
|
||||||
* potentially valid values rather than -1 or 0).
|
|
||||||
*/
|
|
||||||
public boolean isValid ()
|
|
||||||
{
|
|
||||||
return (targetSceneId > 0) && (targetPortalId > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a clone of this instance.
|
|
||||||
*/
|
|
||||||
public Object clone ()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return (Portal)super.clone();
|
|
||||||
} catch (CloneNotSupportedException cnse) {
|
|
||||||
throw new RuntimeException("Portal.clone() failed " + cnse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Portal equality is determined by portal id.
|
|
||||||
*/
|
|
||||||
public boolean equals (Object other)
|
|
||||||
{
|
|
||||||
return (other instanceof Portal) &&
|
|
||||||
((Portal) other).portalId == portalId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes a reasonable hashcode for portal instances.
|
|
||||||
*/
|
|
||||||
public int hashCode ()
|
|
||||||
{
|
|
||||||
return portalId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.io.SimpleStreamableObject;
|
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extends {@link Location} with the data and functionality needed to
|
|
||||||
* represent a particular user's location in a scene.
|
|
||||||
*/
|
|
||||||
public class SceneLocation extends SimpleStreamableObject
|
|
||||||
implements DSet.Entry
|
|
||||||
{
|
|
||||||
/** The oid of the body that occupies this location. */
|
|
||||||
public int bodyOid;
|
|
||||||
|
|
||||||
/** The actual location, which is interpreted by the display system. */
|
|
||||||
public Location loc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a scene location with the specified information.
|
|
||||||
*/
|
|
||||||
public SceneLocation (Location loc, int bodyOid)
|
|
||||||
{
|
|
||||||
this.loc = loc;
|
|
||||||
this.bodyOid = bodyOid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a blank instance suitable for unserialization.
|
|
||||||
*/
|
|
||||||
public SceneLocation ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public Comparable getKey ()
|
|
||||||
{
|
|
||||||
if (_key == null) {
|
|
||||||
_key = Integer.valueOf(bodyOid);
|
|
||||||
}
|
|
||||||
return _key;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public boolean equals (Object other)
|
|
||||||
{
|
|
||||||
// TEMP
|
|
||||||
if (other instanceof Location) {
|
|
||||||
com.threerings.whirled.spot.Log.warning(
|
|
||||||
"Illegal compare of SceneLocation and Location!!!");
|
|
||||||
Thread.dumpStack(); // this will help us find logic errors,
|
|
||||||
// as a SceneLocation and a Location shouldn't be compared
|
|
||||||
}
|
|
||||||
// END: temp
|
|
||||||
|
|
||||||
return (other instanceof SceneLocation) &&
|
|
||||||
this.loc.equals(((SceneLocation) other).loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public int hashCode ()
|
|
||||||
{
|
|
||||||
return loc.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used for {@link #getKey}. */
|
|
||||||
protected transient Integer _key;
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.chat.data.ChatCodes;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.SceneCodes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains codes used by the Spot invocation services.
|
|
||||||
*/
|
|
||||||
public interface SpotCodes extends ChatCodes, SceneCodes
|
|
||||||
{
|
|
||||||
/** An error code indicating that the portal specified in a
|
|
||||||
* traversePortal request does not exist. */
|
|
||||||
public static final String NO_SUCH_PORTAL = "m.no_such_portal";
|
|
||||||
|
|
||||||
/** An error code indicating that a location is occupied. Usually
|
|
||||||
* generated by a failed changeLoc request. */
|
|
||||||
public static final String LOCATION_OCCUPIED = "m.location_occupied";
|
|
||||||
|
|
||||||
/** An error code indicating that a location is not valid. Usually
|
|
||||||
* generated by a failed changeLoc request. */
|
|
||||||
public static final String INVALID_LOCATION = "m.invalid_location";
|
|
||||||
|
|
||||||
/** An error code indicating that a cluster is not valid. Usually
|
|
||||||
* generated by a failed joinCluster request. */
|
|
||||||
public static final String NO_SUCH_CLUSTER = "m.no_such_cluster";
|
|
||||||
|
|
||||||
/** An error code indicating that a cluster is full. Usually generated
|
|
||||||
* by a failed joinCluster request. */
|
|
||||||
public static final String CLUSTER_FULL = "m.cluster_full";
|
|
||||||
|
|
||||||
/** The chat type code with which we register our cluster auxiliary
|
|
||||||
* chat objects. Chat display implementations should interpret chat
|
|
||||||
* messages with this type accordingly. */
|
|
||||||
public static final String CLUSTER_CHAT_TYPE = "clusterChat";
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.client.InvocationService;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
|
||||||
import com.threerings.whirled.client.SceneService;
|
|
||||||
import com.threerings.whirled.data.SceneMarshaller;
|
|
||||||
import com.threerings.whirled.spot.client.SpotService;
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the implementation of the {@link SpotService} interface
|
|
||||||
* that marshalls the arguments and delivers the request to the provider
|
|
||||||
* on the server. Also provides an implementation of the response listener
|
|
||||||
* interfaces that marshall the response arguments and deliver them back
|
|
||||||
* to the requesting client.
|
|
||||||
*/
|
|
||||||
public class SpotMarshaller extends InvocationMarshaller
|
|
||||||
implements SpotService
|
|
||||||
{
|
|
||||||
/** The method id used to dispatch {@link #changeLocation} requests. */
|
|
||||||
public static final int CHANGE_LOCATION = 1;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void changeLocation (Client arg1, int arg2, Location arg3, InvocationService.ConfirmListener arg4)
|
|
||||||
{
|
|
||||||
InvocationMarshaller.ConfirmMarshaller listener4 = new InvocationMarshaller.ConfirmMarshaller();
|
|
||||||
listener4.listener = arg4;
|
|
||||||
sendRequest(arg1, CHANGE_LOCATION, new Object[] {
|
|
||||||
Integer.valueOf(arg2), arg3, listener4
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #clusterSpeak} requests. */
|
|
||||||
public static final int CLUSTER_SPEAK = 2;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void clusterSpeak (Client arg1, String arg2, byte arg3)
|
|
||||||
{
|
|
||||||
sendRequest(arg1, CLUSTER_SPEAK, new Object[] {
|
|
||||||
arg2, Byte.valueOf(arg3)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #joinCluster} requests. */
|
|
||||||
public static final int JOIN_CLUSTER = 3;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void joinCluster (Client arg1, int arg2, InvocationService.ConfirmListener arg3)
|
|
||||||
{
|
|
||||||
InvocationMarshaller.ConfirmMarshaller listener3 = new InvocationMarshaller.ConfirmMarshaller();
|
|
||||||
listener3.listener = arg3;
|
|
||||||
sendRequest(arg1, JOIN_CLUSTER, new Object[] {
|
|
||||||
Integer.valueOf(arg2), listener3
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #traversePortal} requests. */
|
|
||||||
public static final int TRAVERSE_PORTAL = 4;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void traversePortal (Client arg1, int arg2, int arg3, int arg4, SceneService.SceneMoveListener arg5)
|
|
||||||
{
|
|
||||||
SceneMarshaller.SceneMoveMarshaller listener5 = new SceneMarshaller.SceneMoveMarshaller();
|
|
||||||
listener5.listener = arg5;
|
|
||||||
sendRequest(arg1, TRAVERSE_PORTAL, new Object[] {
|
|
||||||
Integer.valueOf(arg2), Integer.valueOf(arg3), Integer.valueOf(arg4), listener5
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes available the spot scene information that the server needs to do
|
|
||||||
* its business.
|
|
||||||
*/
|
|
||||||
public interface SpotScene
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns a {@link Portal} object for the portal with the specified
|
|
||||||
* id or null if no portal exists with that id.
|
|
||||||
*/
|
|
||||||
public Portal getPortal (int portalId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of portals in this scene.
|
|
||||||
*/
|
|
||||||
public int getPortalCount ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over the portals in this scene.
|
|
||||||
*/
|
|
||||||
public Iterator getPortals ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the portal id that should be assigned to the next portal
|
|
||||||
* added to this scene.
|
|
||||||
*/
|
|
||||||
public short getNextPortalId ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the portal that represents the default entrance to this
|
|
||||||
* scene. If a body enters the scene at logon time rather than
|
|
||||||
* entering from some other scene, this is the portal at which they
|
|
||||||
* would appear.
|
|
||||||
*/
|
|
||||||
public Portal getDefaultEntrance ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a portal to this scene, immediately making the requisite
|
|
||||||
* modifications to the underlying scene model. The portal id should
|
|
||||||
* have already been assigned using the value obtained from {@link
|
|
||||||
* #getNextPortalId}.
|
|
||||||
*/
|
|
||||||
public void addPortal (Portal portal);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the specified portal from the scene.
|
|
||||||
*/
|
|
||||||
public void removePortal (Portal portal);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default entrance in this scene, immediately making the
|
|
||||||
* requisite modifications to the underlying scene model.
|
|
||||||
*/
|
|
||||||
public void setDefaultEntrance (Portal portal);
|
|
||||||
}
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import com.samskivert.util.HashIntMap;
|
|
||||||
|
|
||||||
import com.threerings.whirled.spot.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of the {@link SpotScene} interface.
|
|
||||||
*/
|
|
||||||
public class SpotSceneImpl
|
|
||||||
implements SpotScene
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates an instance that will obtain data from the supplied spot
|
|
||||||
* scene model.
|
|
||||||
*/
|
|
||||||
public SpotSceneImpl (SpotSceneModel smodel)
|
|
||||||
{
|
|
||||||
_smodel = smodel;
|
|
||||||
readPortals();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void readPortals ()
|
|
||||||
{
|
|
||||||
_portals.clear();
|
|
||||||
for (int ii = 0, ll = _smodel.portals.length; ii < ll; ii++) {
|
|
||||||
Portal port = _smodel.portals[ii];
|
|
||||||
_portals.put(port.portalId, port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a blank scene implementation.
|
|
||||||
*/
|
|
||||||
public SpotSceneImpl ()
|
|
||||||
{
|
|
||||||
_smodel = new SpotSceneModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public Portal getPortal (int portalId)
|
|
||||||
{
|
|
||||||
return (Portal)_portals.get(portalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public int getPortalCount ()
|
|
||||||
{
|
|
||||||
return _portals.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public Iterator getPortals ()
|
|
||||||
{
|
|
||||||
return _portals.values().iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public short getNextPortalId ()
|
|
||||||
{
|
|
||||||
// compute a new portal id for our friend the portal
|
|
||||||
for (short ii = 1; ii < MAX_PORTAL_ID; ii++) {
|
|
||||||
if (!_portals.containsKey(ii)) {
|
|
||||||
return ii;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (short)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public Portal getDefaultEntrance ()
|
|
||||||
{
|
|
||||||
return getPortal(_smodel.defaultEntranceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void addPortal (Portal portal)
|
|
||||||
{
|
|
||||||
if (portal.portalId <= 0) {
|
|
||||||
Log.warning("Refusing to add zero-id portal " +
|
|
||||||
"[scene=" + this + ", portal=" + portal + "].");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add it to our model
|
|
||||||
_smodel.addPortal(portal);
|
|
||||||
|
|
||||||
// and slap it into our table
|
|
||||||
_portals.put(portal.portalId, portal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void removePortal (Portal portal)
|
|
||||||
{
|
|
||||||
// remove the portal from our mapping
|
|
||||||
_portals.remove(portal.portalId);
|
|
||||||
|
|
||||||
// remove it from the model
|
|
||||||
_smodel.removePortal(portal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used when we're being parsed from an XML scene model.
|
|
||||||
*/
|
|
||||||
public void setDefaultEntranceId (int defaultEntranceId)
|
|
||||||
{
|
|
||||||
_smodel.defaultEntranceId = defaultEntranceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void setDefaultEntrance (Portal portal)
|
|
||||||
{
|
|
||||||
_smodel.defaultEntranceId = (portal == null) ? -1 : portal.portalId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This should be called if a scene update was received that caused
|
|
||||||
* our underlying scene model to change.
|
|
||||||
*/
|
|
||||||
public void updateReceived ()
|
|
||||||
{
|
|
||||||
readPortals();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A casted reference to our scene model. */
|
|
||||||
protected SpotSceneModel _smodel;
|
|
||||||
|
|
||||||
/** A mapping from portal id to portal. */
|
|
||||||
protected HashIntMap _portals = new HashIntMap();
|
|
||||||
|
|
||||||
/** We don't allow more than ~32k portals in a scene. Things would
|
|
||||||
* slow down *way* before we got there. */
|
|
||||||
protected static final int MAX_PORTAL_ID = Short.MAX_VALUE;
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.samskivert.util.ArrayUtil;
|
|
||||||
import com.samskivert.util.ListUtil;
|
|
||||||
|
|
||||||
import com.threerings.io.SimpleStreamableObject;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.AuxModel;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The spot scene model extends the standard scene model with information
|
|
||||||
* on portals. Portals are referenced by an identifier, unique within the
|
|
||||||
* scene and unchanging, so that portals can stably reference the target
|
|
||||||
* portal in the scene to which they connect.
|
|
||||||
*/
|
|
||||||
public class SpotSceneModel extends SimpleStreamableObject
|
|
||||||
implements AuxModel
|
|
||||||
{
|
|
||||||
/** An array containing all portals in this scene. */
|
|
||||||
public Portal[] portals = new Portal[0];
|
|
||||||
|
|
||||||
/** The portal id of the default entrance to this scene. If a body
|
|
||||||
* enters the scene without coming from another scene, this is the
|
|
||||||
* portal at which they would appear. */
|
|
||||||
public int defaultEntranceId = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a portal to this scene model.
|
|
||||||
*/
|
|
||||||
public void addPortal (Portal portal)
|
|
||||||
{
|
|
||||||
portals = (Portal[])ArrayUtil.append(portals, portal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a portal from this model.
|
|
||||||
*/
|
|
||||||
public void removePortal (Portal portal)
|
|
||||||
{
|
|
||||||
int pidx = ListUtil.indexOf(portals, portal);
|
|
||||||
if (pidx != -1) {
|
|
||||||
portals = (Portal[])ArrayUtil.splice(portals, pidx, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public Object clone ()
|
|
||||||
throws CloneNotSupportedException
|
|
||||||
{
|
|
||||||
SpotSceneModel model = (SpotSceneModel)super.clone();
|
|
||||||
// clone our portals individually
|
|
||||||
model.portals = new Portal[portals.length];
|
|
||||||
for (int ii = 0, ll = portals.length; ii < ll; ii++) {
|
|
||||||
model.portals[ii] = (Portal)portals[ii].clone();
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locates and returns the {@link SpotSceneModel} among the auxiliary
|
|
||||||
* scene models associated with the supplied scene
|
|
||||||
* model. <code>null</code> is returned if no spot scene model could
|
|
||||||
* be found.
|
|
||||||
*/
|
|
||||||
public static SpotSceneModel getSceneModel (SceneModel model)
|
|
||||||
{
|
|
||||||
for (int ii = 0; ii < model.auxModels.length; ii++) {
|
|
||||||
if (model.auxModels[ii] instanceof SpotSceneModel) {
|
|
||||||
return (SpotSceneModel)model.auxModels[ii];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.data;
|
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DSet;
|
|
||||||
import com.threerings.whirled.data.SceneObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extends the {@link SceneObject} with information specific to spots.
|
|
||||||
*/
|
|
||||||
public class SpotSceneObject extends SceneObject
|
|
||||||
{
|
|
||||||
// AUTO-GENERATED: FIELDS START
|
|
||||||
/** The field name of the <code>occupantLocs</code> field. */
|
|
||||||
public static final String OCCUPANT_LOCS = "occupantLocs";
|
|
||||||
|
|
||||||
/** The field name of the <code>clusters</code> field. */
|
|
||||||
public static final String CLUSTERS = "clusters";
|
|
||||||
// AUTO-GENERATED: FIELDS END
|
|
||||||
|
|
||||||
/** A distributed set containing {@link SceneLocation} records for all
|
|
||||||
* occupants of this scene. */
|
|
||||||
public DSet occupantLocs = new DSet();
|
|
||||||
|
|
||||||
/** Contains information on all {@link Cluster}s in this scene. */
|
|
||||||
public DSet clusters = new DSet();
|
|
||||||
|
|
||||||
// AUTO-GENERATED: METHODS START
|
|
||||||
/**
|
|
||||||
* Requests that the specified entry be added to the
|
|
||||||
* <code>occupantLocs</code> set. The set will not change until the event is
|
|
||||||
* actually propagated through the system.
|
|
||||||
*/
|
|
||||||
public void addToOccupantLocs (DSet.Entry elem)
|
|
||||||
{
|
|
||||||
requestEntryAdd(OCCUPANT_LOCS, occupantLocs, elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the entry matching the supplied key be removed from
|
|
||||||
* the <code>occupantLocs</code> set. The set will not change until the
|
|
||||||
* event is actually propagated through the system.
|
|
||||||
*/
|
|
||||||
public void removeFromOccupantLocs (Comparable key)
|
|
||||||
{
|
|
||||||
requestEntryRemove(OCCUPANT_LOCS, occupantLocs, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the specified entry be updated in the
|
|
||||||
* <code>occupantLocs</code> set. The set will not change until the event is
|
|
||||||
* actually propagated through the system.
|
|
||||||
*/
|
|
||||||
public void updateOccupantLocs (DSet.Entry elem)
|
|
||||||
{
|
|
||||||
requestEntryUpdate(OCCUPANT_LOCS, occupantLocs, elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the <code>occupantLocs</code> field be set to the
|
|
||||||
* specified value. Generally one only adds, updates and removes
|
|
||||||
* entries of a distributed set, but certain situations call for a
|
|
||||||
* complete replacement of the set value. The local value will be
|
|
||||||
* updated immediately and an event will be propagated through the
|
|
||||||
* system to notify all listeners that the attribute did
|
|
||||||
* change. Proxied copies of this object (on clients) will apply the
|
|
||||||
* value change when they received the attribute changed notification.
|
|
||||||
*/
|
|
||||||
public void setOccupantLocs (DSet value)
|
|
||||||
{
|
|
||||||
requestAttributeChange(OCCUPANT_LOCS, value, this.occupantLocs);
|
|
||||||
this.occupantLocs = (value == null) ? null : value.typedClone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the specified entry be added to the
|
|
||||||
* <code>clusters</code> set. The set will not change until the event is
|
|
||||||
* actually propagated through the system.
|
|
||||||
*/
|
|
||||||
public void addToClusters (DSet.Entry elem)
|
|
||||||
{
|
|
||||||
requestEntryAdd(CLUSTERS, clusters, elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the entry matching the supplied key be removed from
|
|
||||||
* the <code>clusters</code> set. The set will not change until the
|
|
||||||
* event is actually propagated through the system.
|
|
||||||
*/
|
|
||||||
public void removeFromClusters (Comparable key)
|
|
||||||
{
|
|
||||||
requestEntryRemove(CLUSTERS, clusters, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the specified entry be updated in the
|
|
||||||
* <code>clusters</code> set. The set will not change until the event is
|
|
||||||
* actually propagated through the system.
|
|
||||||
*/
|
|
||||||
public void updateClusters (DSet.Entry elem)
|
|
||||||
{
|
|
||||||
requestEntryUpdate(CLUSTERS, clusters, elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that the <code>clusters</code> field be set to the
|
|
||||||
* specified value. Generally one only adds, updates and removes
|
|
||||||
* entries of a distributed set, but certain situations call for a
|
|
||||||
* complete replacement of the set value. The local value will be
|
|
||||||
* updated immediately and an event will be propagated through the
|
|
||||||
* system to notify all listeners that the attribute did
|
|
||||||
* change. Proxied copies of this object (on clients) will apply the
|
|
||||||
* value change when they received the attribute changed notification.
|
|
||||||
*/
|
|
||||||
public void setClusters (DSet value)
|
|
||||||
{
|
|
||||||
requestAttributeChange(CLUSTERS, value, this.clusters);
|
|
||||||
this.clusters = (value == null) ? null : value.typedClone();
|
|
||||||
}
|
|
||||||
// AUTO-GENERATED: METHODS END
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,108 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- $Id: package.html,v 1.1 2001/11/13 00:12:20 mdb Exp $ -->
|
|
||||||
</head>
|
|
||||||
<body bgcolor="white">
|
|
||||||
|
|
||||||
Extends the Whirled services with the notion of locations, clusters,
|
|
||||||
coordinates and orientation.
|
|
||||||
|
|
||||||
<p> The basic Whirled services facilitate a game that provides a
|
|
||||||
connected set of scenes and the ability for the bodies to move from
|
|
||||||
a scene to its neighboring scenes. The Spot package extends those
|
|
||||||
services by providing the notion of locations within scenes which a
|
|
||||||
body can occupy and which, while occupied, cannot be occupied by
|
|
||||||
other bodies.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> The philosophy is that a game that uses these services wants to
|
|
||||||
create a constrained universe where a body cannot simply stand
|
|
||||||
anywhere on the screen, but can only stand in a set of predefined
|
|
||||||
locations. This is a simplified mechanism for providing finer
|
|
||||||
grained locality management, such that expensive distance monitoring
|
|
||||||
algorithms need not be used to determine who can interact (speak)
|
|
||||||
with others in a particular scene. For many games, the overhead of
|
|
||||||
tracking each users' position in near-realtime coupled with a
|
|
||||||
complex message broadcasting system that dispatches messages to
|
|
||||||
users in geometric proximity to one another is serious overkill and
|
|
||||||
does not add sufficient value to the game to merit inclusion.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><b>Locations and clusters</b><br>
|
|
||||||
|
|
||||||
The Spot package provides a functional approximation in the form of
|
|
||||||
clusters of locations, with predefined coordinates, that are
|
|
||||||
sufficiently proximal that bodies in that cluster of locations can
|
|
||||||
all speak to one another. The locations for a particular scene are
|
|
||||||
specified in advance which serves the additional purpose of putting
|
|
||||||
a limit on the number of bodies that can be standing (and
|
|
||||||
participating) in a particular scene. This puts a natural upper
|
|
||||||
bound on the amount of network traffic that will be generated by the
|
|
||||||
need to broadcast scene updates to all occupants of a scene.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> Locations also serve as entry and exit points for a scene,
|
|
||||||
providing a means both for the graphical user interface to identify
|
|
||||||
the location at which bodies enter and exit a scene as well as
|
|
||||||
providing a spatial context for the connections between scenes
|
|
||||||
(i.e. the exit to the scene to the north can be located in the
|
|
||||||
northward part of a scene display).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><b>Orientation</b><br>
|
|
||||||
|
|
||||||
Locations define a notion of orientation which is assigned a priori,
|
|
||||||
along with the coordinates of the location and which can be
|
|
||||||
interpreted by the graphical display as the direction that body
|
|
||||||
sprites should face when standing on that location. Clusters of
|
|
||||||
locations can be constructed such that all of the bodies standing in
|
|
||||||
that cluster appear to be facing one another which provides visible
|
|
||||||
reinforcement that members of the cluster can "hear" the
|
|
||||||
conversation, while members of other clusters cannot. The
|
|
||||||
orientation of entry and exit locations are also useful in
|
|
||||||
establishing an initial orientation for a body sprite that enters a
|
|
||||||
scene based on the visualization of the entrance mechanism (i.e. if
|
|
||||||
they appear to enter through the door, the body sprite should be
|
|
||||||
oriented as if it just walked in the proper direction through the
|
|
||||||
door).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> Because the Spot services redefine the scope at which speak
|
|
||||||
messages are normally distributed (the Crowd services would, by
|
|
||||||
default, have speak messages dispatched to everyone in the entire
|
|
||||||
scene because the scene is a place and the default chat mechanisms
|
|
||||||
dispatch speak messages to all occupants of a place), it defines an
|
|
||||||
additional communication mode known as shouting, which conveys the
|
|
||||||
message to everyone in the entire scene.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><b>Portals</b><br>
|
|
||||||
|
|
||||||
Portals are a combination of locations and the standard Whirled
|
|
||||||
notion of neighboring scenes. They contain the coordinates to which
|
|
||||||
a body sprite would traverse prior to exiting to a neighboring scene
|
|
||||||
(generally so that they appear to walk to whatever visual
|
|
||||||
representation of the portal is provided by the scene, like a door
|
|
||||||
or perhaps simply the edge of the scene). Conversely, they represent
|
|
||||||
the coordinates at which a body arriving from same neighboring scene
|
|
||||||
would appear in the displayed scene.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p><b>Example display</b><br>
|
|
||||||
|
|
||||||
This is an example of how these concepts might look in a game
|
|
||||||
providing top-down 2D display of its scenes. <br>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<center>
|
|
||||||
<img align="center" src="images/scene.png" alt="Example scene image">
|
|
||||||
</center>
|
|
||||||
|
|
||||||
<p> The arrows would, of course, not be rendered but are shown to
|
|
||||||
indicate the presence of locations (and portals) and their
|
|
||||||
associated orientation information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.server;
|
|
||||||
|
|
||||||
import com.threerings.whirled.server.WhirledClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extends the Whirled client and handles the necessary notifications that
|
|
||||||
* take place when a user logs off to let the clients displaying the scene
|
|
||||||
* they were occupying know that they didn't exit via a portal, but
|
|
||||||
* instead just disappeared.
|
|
||||||
*/
|
|
||||||
public class SpotClient extends WhirledClient
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.spot.server;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.client.InvocationService;
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.server.InvocationDispatcher;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
import com.threerings.whirled.client.SceneService;
|
|
||||||
import com.threerings.whirled.data.SceneMarshaller;
|
|
||||||
import com.threerings.whirled.spot.client.SpotService;
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
import com.threerings.whirled.spot.data.SpotMarshaller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches requests to the {@link SpotProvider}.
|
|
||||||
*/
|
|
||||||
public class SpotDispatcher extends InvocationDispatcher
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a dispatcher that may be registered to dispatch invocation
|
|
||||||
* service requests for the specified provider.
|
|
||||||
*/
|
|
||||||
public SpotDispatcher (SpotProvider provider)
|
|
||||||
{
|
|
||||||
this.provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public InvocationMarshaller createMarshaller ()
|
|
||||||
{
|
|
||||||
return new SpotMarshaller();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchRequest (
|
|
||||||
ClientObject source, int methodId, Object[] args)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case SpotMarshaller.CHANGE_LOCATION:
|
|
||||||
((SpotProvider)provider).changeLocation(
|
|
||||||
source,
|
|
||||||
((Integer)args[0]).intValue(), (Location)args[1], (InvocationService.ConfirmListener)args[2]
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SpotMarshaller.CLUSTER_SPEAK:
|
|
||||||
((SpotProvider)provider).clusterSpeak(
|
|
||||||
source,
|
|
||||||
(String)args[0], ((Byte)args[1]).byteValue()
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SpotMarshaller.JOIN_CLUSTER:
|
|
||||||
((SpotProvider)provider).joinCluster(
|
|
||||||
source,
|
|
||||||
((Integer)args[0]).intValue(), (InvocationService.ConfirmListener)args[1]
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SpotMarshaller.TRAVERSE_PORTAL:
|
|
||||||
((SpotProvider)provider).traversePortal(
|
|
||||||
source,
|
|
||||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), ((Integer)args[2]).intValue(), (SceneService.SceneMoveListener)args[3]
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchRequest(source, methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,324 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.server;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
import com.threerings.util.MessageManager;
|
|
||||||
import com.threerings.util.Name;
|
|
||||||
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.dobj.RootDObjectManager;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
import com.threerings.presents.server.InvocationProvider;
|
|
||||||
|
|
||||||
import com.threerings.crowd.chat.data.ChatCodes;
|
|
||||||
import com.threerings.crowd.chat.server.SpeakProvider;
|
|
||||||
import com.threerings.crowd.data.BodyObject;
|
|
||||||
import com.threerings.crowd.server.PlaceRegistry;
|
|
||||||
|
|
||||||
import com.threerings.whirled.client.SceneService.SceneMoveListener;
|
|
||||||
import com.threerings.whirled.data.ScenedBodyObject;
|
|
||||||
import com.threerings.whirled.server.SceneManager;
|
|
||||||
import com.threerings.whirled.server.SceneRegistry;
|
|
||||||
|
|
||||||
import com.threerings.whirled.spot.Log;
|
|
||||||
import com.threerings.whirled.spot.client.SpotService;
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
import com.threerings.whirled.spot.data.Portal;
|
|
||||||
import com.threerings.whirled.spot.data.SpotCodes;
|
|
||||||
import com.threerings.whirled.spot.data.SpotScene;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the server-side implementation of the spot services.
|
|
||||||
*/
|
|
||||||
public class SpotProvider
|
|
||||||
implements SpotCodes, InvocationProvider
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a spot provider that can be registered with the invocation
|
|
||||||
* manager to handle spot services.
|
|
||||||
*/
|
|
||||||
public SpotProvider (RootDObjectManager omgr, PlaceRegistry plreg,
|
|
||||||
SceneRegistry screg)
|
|
||||||
{
|
|
||||||
// we'll need these later
|
|
||||||
_plreg = plreg;
|
|
||||||
_screg = screg;
|
|
||||||
_omgr = omgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a {@link SpotService#traversePortal} request.
|
|
||||||
*/
|
|
||||||
public void traversePortal (ClientObject caller, int sceneId, int portalId,
|
|
||||||
int destSceneVer, SceneMoveListener listener)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
// 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 + "].");
|
|
||||||
InvocationMarshaller.setNoResponse(listener);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// avoid cluttering up the method declaration with final keywords
|
|
||||||
final BodyObject fsource = (BodyObject)caller;
|
|
||||||
final int fportalId = portalId;
|
|
||||||
final int fsceneVer = destSceneVer;
|
|
||||||
final SceneMoveListener flistener = listener;
|
|
||||||
|
|
||||||
// obtain the source scene
|
|
||||||
final SpotSceneManager srcmgr = (SpotSceneManager)
|
|
||||||
_screg.getSceneManager(sceneId);
|
|
||||||
if (srcmgr == null) {
|
|
||||||
Log.warning("Traverse portal missing source scene " +
|
|
||||||
"[user=" + fsource.who() + ", sceneId=" + sceneId +
|
|
||||||
", portalId=" + portalId + "].");
|
|
||||||
throw new InvocationException(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// obtain the destination scene and location id
|
|
||||||
SpotScene rss = (SpotScene)srcmgr.getScene();
|
|
||||||
final Portal fdest = rss.getPortal(portalId);
|
|
||||||
|
|
||||||
// give the source scene manager a chance to do access control
|
|
||||||
String errmsg = srcmgr.mayTraversePortal(fsource, fdest);
|
|
||||||
if (errmsg != null) {
|
|
||||||
throw new InvocationException(errmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()) +
|
|
||||||
"].");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
protected void finishTraversePortalRequest (
|
|
||||||
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);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// move to the place object associated with this scene
|
|
||||||
_screg.sceneprov.effectSceneMove(
|
|
||||||
source, destmgr, sceneVer, listener);
|
|
||||||
} catch (InvocationException sfe) {
|
|
||||||
listener.requestFailed(sfe.getMessage());
|
|
||||||
// and let the destination scene manager know that we're no
|
|
||||||
// longer coming in
|
|
||||||
destmgr.clearEnteringBody(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a {@link SpotService#changeLocation} request.
|
|
||||||
*/
|
|
||||||
public void changeLocation (ClientObject caller, int sceneId, Location loc,
|
|
||||||
SpotService.ConfirmListener listener)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
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 + "].");
|
|
||||||
throw new InvocationException(INVALID_LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
// look up the scene manager for the specified scene
|
|
||||||
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 +"].");
|
|
||||||
throw new InvocationException(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass the buck to yon scene manager
|
|
||||||
smgr.handleChangeLoc(source, loc);
|
|
||||||
|
|
||||||
// if that method finished, we're good to go
|
|
||||||
listener.requestProcessed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a {@link SpotService#joinCluster} request.
|
|
||||||
*/
|
|
||||||
public void joinCluster (ClientObject caller, int friendOid,
|
|
||||||
SpotService.ConfirmListener listener)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
int sceneId = getCallerSceneId(caller);
|
|
||||||
BodyObject source = (BodyObject)caller;
|
|
||||||
|
|
||||||
// look up the scene manager for the specified scene
|
|
||||||
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 +"].");
|
|
||||||
throw new InvocationException(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass the buck to yon scene manager
|
|
||||||
smgr.handleJoinCluster(source, friendOid);
|
|
||||||
|
|
||||||
// if that method finished, we're good to go
|
|
||||||
listener.requestProcessed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles request to generate a speak message in the specified cluster.
|
|
||||||
*/
|
|
||||||
public void clusterSpeak (ClientObject caller, String message, byte mode)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
// ensure the caller has normal chat access
|
|
||||||
BodyObject source = (BodyObject)caller;
|
|
||||||
String errmsg = source.checkAccess(ChatCodes.CHAT_ACCESS, null);
|
|
||||||
if (errmsg != null) {
|
|
||||||
SpeakProvider.sendFeedback(source,
|
|
||||||
MessageManager.GLOBAL_BUNDLE, errmsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @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 message the text of the chat message.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
if (smgr == null) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains the scene id occupied by the supplied caller.
|
|
||||||
*
|
|
||||||
* @exception InvocationException thrown if the caller does not
|
|
||||||
* implement {@link ScenedBodyObject}.
|
|
||||||
*/
|
|
||||||
protected static int getCallerSceneId (ClientObject caller)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
if (caller instanceof ScenedBodyObject) {
|
|
||||||
return ((ScenedBodyObject)caller).getSceneId();
|
|
||||||
} else {
|
|
||||||
Log.warning("Can't get scene from non-scened caller " +
|
|
||||||
caller.who() + ".");
|
|
||||||
throw new InvocationException(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The place registry with which we interoperate. */
|
|
||||||
protected PlaceRegistry _plreg;
|
|
||||||
|
|
||||||
/** The scene registry with which we interoperate. */
|
|
||||||
protected SceneRegistry _screg;
|
|
||||||
|
|
||||||
/** The object manager we use to do dobject stuff. */
|
|
||||||
protected RootDObjectManager _omgr;
|
|
||||||
}
|
|
||||||
@@ -1,626 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.server;
|
|
||||||
|
|
||||||
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;
|
|
||||||
import com.threerings.presents.dobj.Subscriber;
|
|
||||||
import com.threerings.presents.dobj.ObjectAccessException;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
|
|
||||||
import com.threerings.crowd.chat.server.SpeakProvider;
|
|
||||||
import com.threerings.crowd.data.BodyObject;
|
|
||||||
import com.threerings.crowd.data.OccupantInfo;
|
|
||||||
import com.threerings.crowd.server.CrowdServer;
|
|
||||||
import com.threerings.whirled.server.SceneManager;
|
|
||||||
|
|
||||||
import com.threerings.whirled.spot.Log;
|
|
||||||
import com.threerings.whirled.spot.data.Cluster;
|
|
||||||
import com.threerings.whirled.spot.data.ClusterObject;
|
|
||||||
import com.threerings.whirled.spot.data.ClusteredBodyObject;
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
import com.threerings.whirled.spot.data.Portal;
|
|
||||||
import com.threerings.whirled.spot.data.SceneLocation;
|
|
||||||
import com.threerings.whirled.spot.data.SpotCodes;
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
public class SpotSceneManager extends SceneManager
|
|
||||||
implements SpotCodes
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Move the specified body to the default portal, if possible.
|
|
||||||
*/
|
|
||||||
public static void moveBodyToDefaultPortal (BodyObject body)
|
|
||||||
{
|
|
||||||
SpotSceneManager mgr = (SpotSceneManager)
|
|
||||||
CrowdServer.plreg.getPlaceManager(body.location);
|
|
||||||
if (mgr != null) {
|
|
||||||
SpotScene scene = (SpotScene)mgr.getScene();
|
|
||||||
if (scene == null) {
|
|
||||||
Log.warning("No scene in moveBodyToDefaultPortal()? " +
|
|
||||||
"[who=" + body.who() +
|
|
||||||
", where=" + mgr.where() + "].");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Location eloc = scene.getDefaultEntrance().getLocation();
|
|
||||||
mgr.handleChangeLoc(body, eloc);
|
|
||||||
} catch (InvocationException ie) {
|
|
||||||
Log.warning("Could not move user to default portal " +
|
|
||||||
"[where=" + mgr.where() + ", who=" + body.who() +
|
|
||||||
", error=" + ie + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
_enterers.put(body.getOid(), portalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called if a body failed to enter our scene after we assigned them
|
|
||||||
* an entering position.
|
|
||||||
*/
|
|
||||||
public void clearEnteringBody (BodyObject body)
|
|
||||||
{
|
|
||||||
_enterers.remove(body.getOid());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
updateLocation(body, portal.getLocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
_ssobj = (SpotSceneObject)_plobj;
|
|
||||||
|
|
||||||
super.didStartup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void gotSceneData ()
|
|
||||||
{
|
|
||||||
super.gotSceneData();
|
|
||||||
|
|
||||||
// keep a casted reference around to our scene
|
|
||||||
_sscene = (SpotScene)_scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void bodyLeft (int bodyOid)
|
|
||||||
{
|
|
||||||
super.bodyLeft(bodyOid);
|
|
||||||
|
|
||||||
// clear out their location information
|
|
||||||
_ssobj.removeFromOccupantLocs(Integer.valueOf(bodyOid));
|
|
||||||
|
|
||||||
// clear any cluster they may occupy
|
|
||||||
removeFromCluster(bodyOid);
|
|
||||||
|
|
||||||
// let's make damned sure they're not in any cluster
|
|
||||||
Iterator cliter = _clusters.values().iterator();
|
|
||||||
while (cliter.hasNext()) {
|
|
||||||
ClusterRecord clrec = (ClusterRecord)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.
|
|
||||||
clrec.destroy(false);
|
|
||||||
cliter.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void insertOccupantInfo (OccupantInfo info, BodyObject body)
|
|
||||||
{
|
|
||||||
super.insertOccupantInfo(info, body);
|
|
||||||
|
|
||||||
// we don't actually populate their occupant info, but instead assign
|
|
||||||
// them their starting location in the scene
|
|
||||||
int portalId = _enterers.remove(body.getOid());
|
|
||||||
Portal entry;
|
|
||||||
if (portalId != -1) {
|
|
||||||
entry = _sscene.getPortal(portalId);
|
|
||||||
if (entry == null) {
|
|
||||||
Log.warning("Body mapped at invalid portal [where=" + where() +
|
|
||||||
", who=" + body.who() +
|
|
||||||
", portalId=" + portalId + "].");
|
|
||||||
entry = _sscene.getDefaultEntrance();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
entry = _sscene.getDefaultEntrance();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
_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.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
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 + "].");
|
|
||||||
throw new InvocationException(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// let our derived classes decide if this is an OK place to stand
|
|
||||||
if (!validateLocation(source, loc)) {
|
|
||||||
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
|
|
||||||
updateLocation(source, loc);
|
|
||||||
|
|
||||||
// remove them from any cluster as they've departed
|
|
||||||
removeFromCluster(source.getOid());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the location of the specified body.
|
|
||||||
*/
|
|
||||||
protected void updateLocation (BodyObject source, Location loc)
|
|
||||||
{
|
|
||||||
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 + "].");
|
|
||||||
Thread.dumpStack();
|
|
||||||
_ssobj.addToOccupantLocs(sloc);
|
|
||||||
} else {
|
|
||||||
_ssobj.updateOccupantLocs(sloc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
if (clrec != null) {
|
|
||||||
clrec.addBody(joiner);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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() +
|
|
||||||
", targetOid=" + targetOid + "].");
|
|
||||||
throw new InvocationException(NO_SUCH_CLUSTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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() +
|
|
||||||
", tloc=" + friend.location + "].");
|
|
||||||
throw new InvocationException(NO_SUCH_CLUSTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if the friend is already in a cluster
|
|
||||||
clrec = getCluster(friend.getOid());
|
|
||||||
if (clrec != null) {
|
|
||||||
clrec.addBody(joiner);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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() + "].");
|
|
||||||
clrec = createClusterRecord();
|
|
||||||
clrec.addBody(friend);
|
|
||||||
clrec.addBody(joiner);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the cluster record instance that we'll use to manage our
|
|
||||||
* cluster.
|
|
||||||
*/
|
|
||||||
protected ClusterRecord createClusterRecord ()
|
|
||||||
{
|
|
||||||
return new ClusterRecord();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
{
|
|
||||||
// nothing to do by default
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the specified user from any cluster they occupy.
|
|
||||||
*/
|
|
||||||
protected void removeFromCluster (int bodyOid)
|
|
||||||
{
|
|
||||||
ClusterRecord clrec = getCluster(bodyOid);
|
|
||||||
if (clrec != null) {
|
|
||||||
clrec.removeBody(bodyOid);
|
|
||||||
// If that was the last person, destroy the cluster
|
|
||||||
if (clrec.size() == 0) {
|
|
||||||
clrec.destroy(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the cluster record for the specified body.
|
|
||||||
*/
|
|
||||||
protected ClusterRecord getCluster (int bodyOid)
|
|
||||||
{
|
|
||||||
ClusteredBodyObject bobj = (ClusteredBodyObject)
|
|
||||||
CrowdServer.omgr.getObject(bodyOid);
|
|
||||||
return (bobj == null) ? null :
|
|
||||||
(ClusterRecord)_clusters.get(bobj.getClusterOid());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
ClusterRecord clrec = getCluster(sourceOid);
|
|
||||||
if (clrec == null) {
|
|
||||||
Log.warning("Non-clustered user requested cluster speak " +
|
|
||||||
"[where=" + where() + ", chatter=" + source +
|
|
||||||
" (" + sourceOid + "), msg=" + message + "].");
|
|
||||||
} else {
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
protected SceneLocation locationForBody (int bodyOid)
|
|
||||||
{
|
|
||||||
return (SceneLocation)_ssobj.occupantLocs.get(Integer.valueOf(bodyOid));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies that the specified cluster can be expanded to include
|
|
||||||
* another body.
|
|
||||||
*/
|
|
||||||
protected boolean canAddBody (ClusterRecord clrec, BodyObject body)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
protected void bodyRemoved (ClusterRecord clrec, BodyObject body)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to manage clusters which are groups of users that can chat to
|
|
||||||
* one another.
|
|
||||||
*/
|
|
||||||
protected class ClusterRecord extends HashIntMap
|
|
||||||
implements Subscriber
|
|
||||||
{
|
|
||||||
public ClusterRecord ()
|
|
||||||
{
|
|
||||||
CrowdServer.omgr.createObject(ClusterObject.class, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addBody (BodyObject body)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
if (!(body instanceof ClusteredBodyObject)) {
|
|
||||||
Log.warning("Refusing to add non-clustered body to cluster " +
|
|
||||||
"[cloid=" + _clobj.getOid() +
|
|
||||||
", size=" + size() + ", who=" + body.who() + "].");
|
|
||||||
throw new InvocationException(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if they're already in the cluster, do nothing
|
|
||||||
if (containsKey(body.getOid())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we can add this body
|
|
||||||
if (!canAddBody(this, body)) {
|
|
||||||
// Log.debug("Cluster full, refusing growth " + this + ".");
|
|
||||||
throw new InvocationException(CLUSTER_FULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure our intrepid joiner is not in any another cluster
|
|
||||||
removeFromCluster(body.getOid());
|
|
||||||
|
|
||||||
put(body.getOid(), body);
|
|
||||||
_ssobj.startTransaction();
|
|
||||||
try {
|
|
||||||
body.startTransaction();
|
|
||||||
try {
|
|
||||||
bodyAdded(this, body); // do the hokey pokey
|
|
||||||
|
|
||||||
if (_clobj != null) {
|
|
||||||
((ClusteredBodyObject)body).setClusterOid(
|
|
||||||
_clobj.getOid());
|
|
||||||
_clobj.addToOccupants(body.getOid());
|
|
||||||
_ssobj.updateClusters(_cluster);
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
body.commitTransaction();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
_ssobj.commitTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log.debug("Added " + body.who() + " to "+ this + ".");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeBody (int bodyOid)
|
|
||||||
{
|
|
||||||
BodyObject body = (BodyObject)remove(bodyOid);
|
|
||||||
if (body == null) {
|
|
||||||
Log.warning("Requested to remove unknown body from cluster " +
|
|
||||||
"[cloid=" + _clobj.getOid() +
|
|
||||||
", size=" + size() + ", who=" + bodyOid + "].");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (body.isActive()) {
|
|
||||||
body.startTransaction();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
_ssobj.startTransaction();
|
|
||||||
try {
|
|
||||||
((ClusteredBodyObject)body).setClusterOid(-1);
|
|
||||||
bodyRemoved(this, body); // do the hokey pokey
|
|
||||||
|
|
||||||
if (_clobj != null) {
|
|
||||||
_clobj.removeFromOccupants(bodyOid);
|
|
||||||
_ssobj.updateClusters(_cluster);
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
_ssobj.commitTransaction();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (body.isActive()) {
|
|
||||||
body.commitTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log.debug("Removed " + bodyOid + " from "+ this + ".");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClusterObject getClusterObject ()
|
|
||||||
{
|
|
||||||
return _clobj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cluster getCluster ()
|
|
||||||
{
|
|
||||||
return _cluster;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void objectAvailable (DObject object)
|
|
||||||
{
|
|
||||||
// keep this feller around
|
|
||||||
_clobj = (ClusterObject)object;
|
|
||||||
_clusters.put(_clobj.getOid(), this);
|
|
||||||
|
|
||||||
// let any mapped users know about our cluster
|
|
||||||
Iterator iter = values().iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
ClusteredBodyObject body = (ClusteredBodyObject)iter.next();
|
|
||||||
body.setClusterOid(_clobj.getOid());
|
|
||||||
_clobj.addToOccupants(((BodyObject)body).getOid());
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure our cluster record and publish it
|
|
||||||
_cluster.clusterOid = _clobj.getOid();
|
|
||||||
_ssobj.addToClusters(_cluster);
|
|
||||||
|
|
||||||
// if we didn't manage to add our creating user when we first
|
|
||||||
// started up, there's no point in our sticking around
|
|
||||||
if (size() == 0) {
|
|
||||||
destroy(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestFailed (int oid, ObjectAccessException cause)
|
|
||||||
{
|
|
||||||
Log.warning("Aiya! Failed to create cluster object " +
|
|
||||||
"[cause=" + cause + ", penders=" + size() + "].");
|
|
||||||
|
|
||||||
// let any mapped users know that we're hosed
|
|
||||||
Iterator iter = values().iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
ClusteredBodyObject body = (ClusteredBodyObject)iter.next();
|
|
||||||
body.setClusterOid(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return "[cluster=" + _cluster + ", size=" + size() + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void destroy (boolean doRemoval)
|
|
||||||
{
|
|
||||||
// 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 (doRemoval) {
|
|
||||||
_clusters.remove(_clobj.getOid());
|
|
||||||
}
|
|
||||||
CrowdServer.omgr.destroyObject(_clobj.getOid());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ClusterObject _clobj;
|
|
||||||
protected Cluster _cluster = new Cluster();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A casted reference to our place object. */
|
|
||||||
protected SpotSceneObject _ssobj;
|
|
||||||
|
|
||||||
/** A casted reference to our scene instance. */
|
|
||||||
protected SpotScene _sscene;
|
|
||||||
|
|
||||||
/** Records with information on all clusters in this scene. */
|
|
||||||
protected HashIntMap _clusters = new HashIntMap();
|
|
||||||
|
|
||||||
/** A mapping of entering bodies to portal ids. */
|
|
||||||
protected IntIntMap _enterers = new IntIntMap();
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.tools;
|
|
||||||
|
|
||||||
import com.threerings.whirled.spot.data.Portal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An editable portal extends the standard portal with information needed
|
|
||||||
* by the loader and editor.
|
|
||||||
*/
|
|
||||||
public class EditablePortal extends Portal
|
|
||||||
{
|
|
||||||
/** The human-readable name of this portal. */
|
|
||||||
public String name;
|
|
||||||
|
|
||||||
/** The human-readable name of the scene to which this portal
|
|
||||||
* links. */
|
|
||||||
public String targetSceneName;
|
|
||||||
|
|
||||||
/** The human-readable name of the portal to which this portal links
|
|
||||||
* in its target scene. */
|
|
||||||
public String targetPortalName;
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.tools.xml;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
import com.samskivert.xml.SetPropertyFieldsRule;
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
import com.samskivert.util.ValueMarshaller;
|
|
||||||
|
|
||||||
import com.threerings.tools.xml.NestableRuleSet;
|
|
||||||
|
|
||||||
import org.apache.commons.digester.Digester;
|
|
||||||
import org.apache.commons.digester.ObjectCreateRule;
|
|
||||||
import org.apache.commons.digester.Rule;
|
|
||||||
|
|
||||||
import org.xml.sax.Attributes;
|
|
||||||
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
import com.threerings.whirled.spot.data.Portal;
|
|
||||||
import com.threerings.whirled.spot.data.SpotSceneModel;
|
|
||||||
import com.threerings.whirled.spot.tools.EditablePortal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to parse a {@link SpotSceneModel} from XML.
|
|
||||||
*/
|
|
||||||
public abstract class SpotSceneRuleSet implements NestableRuleSet
|
|
||||||
{
|
|
||||||
// documentation inherited from interface
|
|
||||||
public String getOuterElement ()
|
|
||||||
{
|
|
||||||
return SpotSceneWriter.OUTER_ELEMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void addRuleInstances (String prefix, Digester digester)
|
|
||||||
{
|
|
||||||
digester.addObjectCreate(prefix, SpotSceneModel.class.getName());
|
|
||||||
|
|
||||||
// set up rules to parse and set our fields
|
|
||||||
digester.addRule(prefix, new SetPropertyFieldsRule());
|
|
||||||
|
|
||||||
// create EditablePortal instances when we see <portal>
|
|
||||||
digester.addRule(prefix + "/portal", new PortalCreateRule(this));
|
|
||||||
digester.addRule(prefix + "/portal", new PortalFieldsRule());
|
|
||||||
digester.addSetNext(prefix + "/portal", "addPortal",
|
|
||||||
Portal.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new instance of the Location class that should be used
|
|
||||||
* with Portals.
|
|
||||||
*/
|
|
||||||
protected abstract Location createLocation ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A rule used to create the portal but also initialize the Location
|
|
||||||
* property within it.
|
|
||||||
*/
|
|
||||||
protected static class PortalCreateRule extends ObjectCreateRule
|
|
||||||
{
|
|
||||||
public PortalCreateRule (SpotSceneRuleSet ruleset)
|
|
||||||
{
|
|
||||||
super(EditablePortal.class.getName());
|
|
||||||
_ruleset = ruleset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void begin (String namespace, String name, Attributes attributes)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
super.begin(namespace, name, attributes);
|
|
||||||
|
|
||||||
// create the empty Location in the Portal
|
|
||||||
Portal p = (Portal) digester.peek();
|
|
||||||
p.loc = _ruleset.createLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SpotSceneRuleSet _ruleset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set fields in the Portal, or in the Location object
|
|
||||||
* contained therein. If there are ambiguous attribute names then..
|
|
||||||
* well. yeah.
|
|
||||||
*/
|
|
||||||
protected static class PortalFieldsRule extends Rule
|
|
||||||
{
|
|
||||||
// documentation inherited
|
|
||||||
public void begin (String namespace, String name, Attributes attrs)
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
Portal portal = (Portal) digester.peek();
|
|
||||||
Class portalClass = portal.getClass();
|
|
||||||
Location loc = portal.loc;
|
|
||||||
Class locClass = loc.getClass();
|
|
||||||
|
|
||||||
// iterate over the attributes, setting public fields where
|
|
||||||
// applicable
|
|
||||||
for (int i = 0; i < attrs.getLength(); i++) {
|
|
||||||
String lname = attrs.getLocalName(i);
|
|
||||||
if (StringUtil.isBlank(lname)) {
|
|
||||||
lname = attrs.getQName(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for a public field with this lname
|
|
||||||
Field field;
|
|
||||||
Object container;
|
|
||||||
try {
|
|
||||||
field = portalClass.getField(lname);
|
|
||||||
container = portal;
|
|
||||||
|
|
||||||
} catch (NoSuchFieldException nsfe) {
|
|
||||||
// if we didn't find the field in the Portal, maybe it's
|
|
||||||
// in the Location
|
|
||||||
try {
|
|
||||||
field = locClass.getField(lname);
|
|
||||||
container = loc;
|
|
||||||
|
|
||||||
} catch (NoSuchFieldException nsfe2) {
|
|
||||||
digester.getLogger().warn(
|
|
||||||
"Skipping property '" + lname +
|
|
||||||
"' for which there is no field.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert the value into the appropriate object type
|
|
||||||
String valstr = attrs.getValue(i);
|
|
||||||
// use the value marshaller to parse the
|
|
||||||
// property based on the type of the target object field
|
|
||||||
Object value = ValueMarshaller.unmarshal(
|
|
||||||
field.getType(), valstr);
|
|
||||||
|
|
||||||
if (digester.getLogger().isDebugEnabled()) {
|
|
||||||
digester.getLogger().debug(" Setting property '" + lname +
|
|
||||||
"' to '" + valstr + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// and finally set the field
|
|
||||||
field.set(container, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.spot.tools.xml;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
import org.xml.sax.helpers.AttributesImpl;
|
|
||||||
|
|
||||||
import com.megginson.sax.DataWriter;
|
|
||||||
import com.threerings.tools.xml.NestableWriter;
|
|
||||||
|
|
||||||
import com.threerings.whirled.spot.Log;
|
|
||||||
import com.threerings.whirled.spot.data.Location;
|
|
||||||
import com.threerings.whirled.spot.data.SpotSceneModel;
|
|
||||||
import com.threerings.whirled.spot.tools.EditablePortal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an XML representation of a {@link SpotSceneModel}.
|
|
||||||
*/
|
|
||||||
public class SpotSceneWriter
|
|
||||||
implements NestableWriter
|
|
||||||
{
|
|
||||||
/** The outer element used to enclose our spot scene definition. */
|
|
||||||
public static final String OUTER_ELEMENT = "spot";
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void write (Object object, DataWriter writer)
|
|
||||||
throws SAXException
|
|
||||||
{
|
|
||||||
SpotSceneModel model = (SpotSceneModel)object;
|
|
||||||
AttributesImpl attrs = new AttributesImpl();
|
|
||||||
addSceneAttributes(model, attrs);
|
|
||||||
writer.startElement("", OUTER_ELEMENT, "", attrs);
|
|
||||||
writeSceneData(model, writer);
|
|
||||||
writer.endElement(OUTER_ELEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addSceneAttributes (SpotSceneModel model,
|
|
||||||
AttributesImpl attrs)
|
|
||||||
{
|
|
||||||
if (model.defaultEntranceId != -1) {
|
|
||||||
attrs.addAttribute("", "defaultEntranceId", "", "",
|
|
||||||
String.valueOf(model.defaultEntranceId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void writeSceneData (SpotSceneModel model, DataWriter writer)
|
|
||||||
throws SAXException
|
|
||||||
{
|
|
||||||
// write out the portal info
|
|
||||||
for (int ii = 0; ii < model.portals.length; ii++) {
|
|
||||||
EditablePortal port = (EditablePortal)model.portals[ii];
|
|
||||||
AttributesImpl attrs = new AttributesImpl();
|
|
||||||
attrs.addAttribute("", "portalId", "", "",
|
|
||||||
String.valueOf(port.portalId));
|
|
||||||
addPortalLocationAttributes(port.loc, attrs);
|
|
||||||
maybeAddAttr(attrs, "name", port.name);
|
|
||||||
maybeAddAttr(attrs, "targetSceneName", port.targetSceneName);
|
|
||||||
maybeAddAttr(attrs, "targetPortalName", port.targetPortalName);
|
|
||||||
writer.emptyElement("", "portal", "", attrs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addPortalLocationAttributes (
|
|
||||||
Location portalLoc, AttributesImpl attrs)
|
|
||||||
{
|
|
||||||
// we just add all the visible fields of the location, but something
|
|
||||||
// more sophisticated could be done
|
|
||||||
Class clazz = portalLoc.getClass();
|
|
||||||
Field[] fields = clazz.getFields();
|
|
||||||
for (int ii=0; ii < fields.length; ii++) {
|
|
||||||
try {
|
|
||||||
attrs.addAttribute("", fields[ii].getName(), "", "",
|
|
||||||
String.valueOf(fields[ii].get(portalLoc)));
|
|
||||||
} catch (IllegalAccessException iae) {
|
|
||||||
Log.warning("Unable to write portal field, skipping " +
|
|
||||||
"[field=" + fields[ii].getName() + ", e=" + iae + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the supplied attribute to the attributes object iff the value
|
|
||||||
* is non-null.
|
|
||||||
*/
|
|
||||||
protected void maybeAddAttr (
|
|
||||||
AttributesImpl attrs, String name, String value)
|
|
||||||
{
|
|
||||||
if (value != null) {
|
|
||||||
attrs.addAttribute("", name, "", "", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.tools.xml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
import org.apache.commons.digester.Digester;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
import com.threerings.tools.xml.NestableRuleSet;
|
|
||||||
import com.threerings.whirled.data.AuxModel;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple class for parsing an editable scene instance.
|
|
||||||
*/
|
|
||||||
public class SceneParser
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Constructs a scene parser that parses scenes with the specified XML
|
|
||||||
* path prefix.
|
|
||||||
*/
|
|
||||||
public SceneParser (String prefix)
|
|
||||||
{
|
|
||||||
// create and configure our digester
|
|
||||||
_digester = new Digester();
|
|
||||||
|
|
||||||
// create our scene rule set
|
|
||||||
SceneRuleSet set = createSceneRuleSet();
|
|
||||||
|
|
||||||
// configure our top-level path prefix
|
|
||||||
if (StringUtil.isBlank(prefix)) {
|
|
||||||
_prefix = set.getOuterElement();
|
|
||||||
} else {
|
|
||||||
_prefix = prefix + "/" + set.getOuterElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the scene rules
|
|
||||||
set.addRuleInstances(_prefix, _digester);
|
|
||||||
|
|
||||||
// add a rule to grab the finished scene model
|
|
||||||
_digester.addSetNext(_prefix, "setScene", SceneModel.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the rule set used to parse our scene.
|
|
||||||
*/
|
|
||||||
protected SceneRuleSet createSceneRuleSet ()
|
|
||||||
{
|
|
||||||
return new SceneRuleSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a {@link NestableRuleSet} for parsing auxiliary scene models.
|
|
||||||
*/
|
|
||||||
public void registerAuxRuleSet (NestableRuleSet set)
|
|
||||||
{
|
|
||||||
// add their outer element to the prefix
|
|
||||||
String prefix = _prefix + "/" + set.getOuterElement();
|
|
||||||
|
|
||||||
// add the rules to generate the aux scene model
|
|
||||||
set.addRuleInstances(prefix, _digester);
|
|
||||||
|
|
||||||
// and add a rule to grab it
|
|
||||||
_digester.addSetNext(prefix, "addAuxModel", AuxModel.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the XML file at the specified path into a scene model
|
|
||||||
* instance.
|
|
||||||
*/
|
|
||||||
public SceneModel parseScene (String path)
|
|
||||||
throws IOException, SAXException
|
|
||||||
{
|
|
||||||
_model = null;
|
|
||||||
_digester.push(this);
|
|
||||||
_digester.parse(new FileInputStream(path));
|
|
||||||
return _model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the parser once the scene is parsed.
|
|
||||||
*/
|
|
||||||
public void setScene (SceneModel model)
|
|
||||||
{
|
|
||||||
_model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String _prefix;
|
|
||||||
protected Digester _digester;
|
|
||||||
protected SceneModel _model;
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.tools.xml;
|
|
||||||
|
|
||||||
import org.apache.commons.digester.Digester;
|
|
||||||
|
|
||||||
import com.samskivert.xml.SetPropertyFieldsRule;
|
|
||||||
|
|
||||||
import com.threerings.tools.xml.NestableRuleSet;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to parse a {@link SceneModel} from XML.
|
|
||||||
*/
|
|
||||||
public class SceneRuleSet implements NestableRuleSet
|
|
||||||
{
|
|
||||||
// documentation inherited from interface
|
|
||||||
public String getOuterElement ()
|
|
||||||
{
|
|
||||||
return SceneWriter.OUTER_ELEMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void addRuleInstances (String prefix, Digester digester)
|
|
||||||
{
|
|
||||||
// this creates the appropriate instance when we encounter our tag
|
|
||||||
digester.addObjectCreate(prefix, getSceneClass().getName());
|
|
||||||
|
|
||||||
// set up rules to parse and set our fields
|
|
||||||
digester.addRule(prefix, new SetPropertyFieldsRule());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This indicates the class (which should extend {@link SceneModel})
|
|
||||||
* to be instantiated during the parsing process.
|
|
||||||
*/
|
|
||||||
protected Class getSceneClass ()
|
|
||||||
{
|
|
||||||
return SceneModel.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.tools.xml;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
import org.xml.sax.helpers.AttributesImpl;
|
|
||||||
|
|
||||||
import com.megginson.sax.DataWriter;
|
|
||||||
import com.threerings.tools.xml.NestableWriter;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.data.AuxModel;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an XML representation of an {@link SceneModel}.
|
|
||||||
*/
|
|
||||||
public class SceneWriter
|
|
||||||
{
|
|
||||||
/** The outer element used to enclose our scene definition. */
|
|
||||||
public static final String OUTER_ELEMENT = "scene";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a writer for writing auxiliary scene models of the
|
|
||||||
* supplied class.
|
|
||||||
*/
|
|
||||||
public void registerAuxWriter (Class aclass, NestableWriter writer)
|
|
||||||
{
|
|
||||||
_auxers.put(aclass, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the supplied scene out to the specified file.
|
|
||||||
*/
|
|
||||||
public void writeScene (File out, SceneModel model)
|
|
||||||
throws IOException, SAXException
|
|
||||||
{
|
|
||||||
FileWriter fout = new FileWriter(out);
|
|
||||||
DataWriter dout = new DataWriter(fout);
|
|
||||||
dout.setIndentStep(2);
|
|
||||||
dout.startDocument();
|
|
||||||
writeSceneModel(model, dout);
|
|
||||||
dout.endDocument();
|
|
||||||
fout.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the data for the supplied {@link SceneModel} to the XML data
|
|
||||||
* writer supplied. The writer should already be configured with the
|
|
||||||
* appropriate indentation level so that this writer can simply output
|
|
||||||
* its elements and allow the calling code to determine where in the
|
|
||||||
* greater scene description file the scene data should live.
|
|
||||||
*/
|
|
||||||
public void writeSceneModel (SceneModel model, DataWriter writer)
|
|
||||||
throws SAXException
|
|
||||||
{
|
|
||||||
AttributesImpl attrs = new AttributesImpl();
|
|
||||||
addSceneAttributes(model, attrs);
|
|
||||||
writer.startElement("", OUTER_ELEMENT, "", attrs);
|
|
||||||
writeSceneData(model, writer);
|
|
||||||
writer.endElement(OUTER_ELEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds attributes to the top-level element before it gets written.
|
|
||||||
*/
|
|
||||||
protected void addSceneAttributes (
|
|
||||||
SceneModel model, AttributesImpl attrs)
|
|
||||||
{
|
|
||||||
attrs.addAttribute("", "name", "", "", model.name);
|
|
||||||
attrs.addAttribute("", "version", "", "",
|
|
||||||
Integer.toString(model.version));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes just the scene data which is handy for derived classes which
|
|
||||||
* may wish to add their own scene data to the scene output.
|
|
||||||
*/
|
|
||||||
protected void writeSceneData (SceneModel model, DataWriter writer)
|
|
||||||
throws SAXException
|
|
||||||
{
|
|
||||||
// write out our auxiliary scene models
|
|
||||||
for (int ii = 0; ii < model.auxModels.length; ii++) {
|
|
||||||
AuxModel amodel = model.auxModels[ii];
|
|
||||||
NestableWriter awriter = (NestableWriter)
|
|
||||||
_auxers.get(amodel.getClass());
|
|
||||||
if (awriter != null) {
|
|
||||||
awriter.write(amodel, writer);
|
|
||||||
} else {
|
|
||||||
Log.warning("No writer registered for auxiliary scene model " +
|
|
||||||
"[mclass=" + amodel.getClass() + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected HashMap _auxers = new HashMap();
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown when an attempt to load a non-existent scene is made on the
|
|
||||||
* repository.
|
|
||||||
*/
|
|
||||||
public class NoSuchSceneException extends Exception
|
|
||||||
{
|
|
||||||
public NoSuchSceneException (int sceneid)
|
|
||||||
{
|
|
||||||
super("No such scene [sceneid=" + sceneid + "]");
|
|
||||||
_sceneid = sceneid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSceneId ()
|
|
||||||
{
|
|
||||||
return _sceneid;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int _sceneid;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.util;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.whirled.data.Scene;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is used by the Whirled services to obtain a {@link Scene}
|
|
||||||
* implementation given a scene model and associated data.
|
|
||||||
*/
|
|
||||||
public interface SceneFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a {@link Scene} implementation given the supplied scene
|
|
||||||
* model and place config.
|
|
||||||
*/
|
|
||||||
public Scene createScene (SceneModel model, PlaceConfig config);
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.util;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.threerings.whirled.Log;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list specialized for storing {@link SceneUpdate} objects.
|
|
||||||
*/
|
|
||||||
public class UpdateList
|
|
||||||
{
|
|
||||||
public UpdateList ()
|
|
||||||
{
|
|
||||||
_updates = new ArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an update to this list. The update must follow appropriately
|
|
||||||
* the chain of updates established by the updates already in the list
|
|
||||||
* (meaning it must operate on one version higher than the most recent
|
|
||||||
* update already in the list).
|
|
||||||
*/
|
|
||||||
public void addUpdate (SceneUpdate update)
|
|
||||||
{
|
|
||||||
if (_minVersion == -1) {
|
|
||||||
// this is our first update, so we initialize our min version
|
|
||||||
_minVersion = update.getSceneVersion();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
int gotVersion = update.getSceneVersion();
|
|
||||||
int expVersion = _minVersion + _updates.size();
|
|
||||||
if (gotVersion > expVersion) {
|
|
||||||
Log.warning("Update continuity broken, flushing list " +
|
|
||||||
"[got=" + update + ", expect=" + expVersion +
|
|
||||||
", ucount=" + _updates.size() + "].");
|
|
||||||
// flush out our old updates and start anew from here
|
|
||||||
_updates.clear();
|
|
||||||
_minVersion = expVersion;
|
|
||||||
|
|
||||||
} else if (gotVersion < expVersion) {
|
|
||||||
// we somehow got an update that's older than updates we
|
|
||||||
// already have? wick wick wack
|
|
||||||
String errmsg = "Invalid update version " +
|
|
||||||
"[want=" + expVersion + ", got=" + update + "]";
|
|
||||||
throw new IllegalArgumentException(errmsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_updates.add(update);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all of the updates that should be applied to a scene with
|
|
||||||
* the specified version to bring it up to date. <code>null</code> is
|
|
||||||
* returned if the scene's version is older than the oldest update in
|
|
||||||
* our list, in which case it cannot be brought up to date by applying
|
|
||||||
* updates from this list.
|
|
||||||
*/
|
|
||||||
public SceneUpdate[] getUpdates (int fromVersion)
|
|
||||||
{
|
|
||||||
if (_minVersion == -1 || fromVersion < _minVersion) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset = fromVersion - _minVersion;
|
|
||||||
int ucount = _updates.size() - offset;
|
|
||||||
SceneUpdate[] updates = new SceneUpdate[ucount];
|
|
||||||
for (int ii = 0; ii < ucount; ii++) {
|
|
||||||
updates[ii] = (SceneUpdate)_updates.get(ii+offset);
|
|
||||||
}
|
|
||||||
return updates;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the supplied actual scene version is in accordance
|
|
||||||
* with the updates contained in this list.
|
|
||||||
*/
|
|
||||||
public boolean validate (int sceneVersion)
|
|
||||||
{
|
|
||||||
return ((_minVersion == -1) || // we have no updates
|
|
||||||
(_minVersion + _updates.size() == sceneVersion));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ArrayList _updates;
|
|
||||||
protected int _minVersion = -1;
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.util;
|
|
||||||
|
|
||||||
import com.threerings.crowd.util.CrowdContext;
|
|
||||||
import com.threerings.whirled.client.SceneDirector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The whirled context provides access to the various managers, etc. that
|
|
||||||
* are needed by the whirled client code.
|
|
||||||
*/
|
|
||||||
public interface WhirledContext extends CrowdContext
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns a reference to the scene director.
|
|
||||||
*/
|
|
||||||
public SceneDirector getSceneDirector ();
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder class that contains a reference to the log object used by
|
|
||||||
* the Whirled Zone services.
|
|
||||||
*/
|
|
||||||
public class Log
|
|
||||||
{
|
|
||||||
public static com.samskivert.util.Log log =
|
|
||||||
new com.samskivert.util.Log("whirled.zone");
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void debug (String message)
|
|
||||||
{
|
|
||||||
log.debug(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void info (String message)
|
|
||||||
{
|
|
||||||
log.info(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void warning (String message)
|
|
||||||
{
|
|
||||||
log.warning(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience function. */
|
|
||||||
public static void logStackTrace (Throwable t)
|
|
||||||
{
|
|
||||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.client;
|
|
||||||
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The zone adapter makes life easier for a class that really only cares
|
|
||||||
* about one or two of the zone observer callbacks and doesn't want to
|
|
||||||
* provide empty implementations of the others. One can either extend zone
|
|
||||||
* adapter, or create an anonymous instance that overrides the desired
|
|
||||||
* callback(s).
|
|
||||||
*
|
|
||||||
* @see ZoneObserver
|
|
||||||
*/
|
|
||||||
public class ZoneAdapter implements ZoneObserver
|
|
||||||
{
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void zoneWillChange (int zoneId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void zoneDidChange (ZoneSummary summary)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void zoneChangeFailed (String reason)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.zone.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.InvocationDecoder;
|
|
||||||
import com.threerings.whirled.zone.client.ZoneReceiver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches calls to a {@link ZoneReceiver} instance.
|
|
||||||
*/
|
|
||||||
public class ZoneDecoder extends InvocationDecoder
|
|
||||||
{
|
|
||||||
/** The generated hash code used to identify this receiver class. */
|
|
||||||
public static final String RECEIVER_CODE = "2d900cf54355111b4bb4befcdff42b82";
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link ZoneReceiver#forcedMove}
|
|
||||||
* notifications. */
|
|
||||||
public static final int FORCED_MOVE = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a decoder that may be registered to dispatch invocation
|
|
||||||
* service notifications to the specified receiver.
|
|
||||||
*/
|
|
||||||
public ZoneDecoder (ZoneReceiver receiver)
|
|
||||||
{
|
|
||||||
this.receiver = receiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public String getReceiverCode ()
|
|
||||||
{
|
|
||||||
return RECEIVER_CODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchNotification (int methodId, Object[] args)
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case FORCED_MOVE:
|
|
||||||
((ZoneReceiver)receiver).forcedMove(
|
|
||||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue()
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchNotification(methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,315 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.client;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.samskivert.util.ResultListener;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.BasicDirector;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
|
|
||||||
import com.threerings.whirled.client.SceneDirector;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.util.WhirledContext;
|
|
||||||
|
|
||||||
import com.threerings.whirled.zone.Log;
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
import com.threerings.whirled.zone.util.ZoneUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The zone director augments the scene services with the notion of zones.
|
|
||||||
* Zones are self-contained, connected groups of scenes. The normal scene
|
|
||||||
* director services can be used to move from scene to scene, but moving
|
|
||||||
* to a new zone requires a special move request which can be accomplished
|
|
||||||
* via the zone director. The zone director also makes available the zone
|
|
||||||
* summary which provides information on the zone which can be used to
|
|
||||||
* generate an overview map or similar.
|
|
||||||
*/
|
|
||||||
public class ZoneDirector extends BasicDirector
|
|
||||||
implements ZoneReceiver, ZoneService.ZoneMoveListener,
|
|
||||||
SceneDirector.MoveHandler
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Constructs a zone director with the supplied context, and delegate
|
|
||||||
* scene director (which the zone director will coordinate with when
|
|
||||||
* moving from scene to scene). A zone director is required on the
|
|
||||||
* client side for systems that wish to use the zone services.
|
|
||||||
*/
|
|
||||||
public ZoneDirector (WhirledContext ctx, SceneDirector scdir)
|
|
||||||
{
|
|
||||||
super(ctx);
|
|
||||||
_ctx = ctx;
|
|
||||||
_scdir = scdir;
|
|
||||||
_scdir.setMoveHandler(this);
|
|
||||||
|
|
||||||
// register for zone notifications
|
|
||||||
_ctx.getClient().getInvocationDirector().registerReceiver(
|
|
||||||
new ZoneDecoder(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the summary for the zone currently occupied by the client
|
|
||||||
* or null if the client does not currently occupy a zone (not a
|
|
||||||
* normal situation).
|
|
||||||
*/
|
|
||||||
public ZoneSummary getZoneSummary ()
|
|
||||||
{
|
|
||||||
return _summary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a zone observer to the list. This observer will subsequently
|
|
||||||
* be notified of effected and failed zone changes.
|
|
||||||
*/
|
|
||||||
public void addZoneObserver (ZoneObserver observer)
|
|
||||||
{
|
|
||||||
_observers.add(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a zone observer from the list.
|
|
||||||
*/
|
|
||||||
public void removeZoneObserver (ZoneObserver observer)
|
|
||||||
{
|
|
||||||
_observers.remove(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that this client move the specified scene in the specified
|
|
||||||
* zone. A request will be made and when the response is received, the
|
|
||||||
* location observers will be notified of success or failure.
|
|
||||||
*/
|
|
||||||
public boolean moveTo (int zoneId, int sceneId)
|
|
||||||
{
|
|
||||||
return moveTo(zoneId, sceneId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that this client move the specified scene in the specified
|
|
||||||
* zone. A request will be made and when the response is received, the
|
|
||||||
* location observers will be notified of success or failure.
|
|
||||||
*/
|
|
||||||
public boolean moveTo (int zoneId, int sceneId, ResultListener rl)
|
|
||||||
{
|
|
||||||
// make sure the zoneId and sceneId are valid
|
|
||||||
if (zoneId < 0 || sceneId < 0) {
|
|
||||||
Log.warning("Refusing moveTo(): invalid sceneId or zoneId " +
|
|
||||||
"[zoneId=" + zoneId + ", sceneId=" + sceneId + "].");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the requested zone is the same as our current zone, we just
|
|
||||||
// want a regular old moveTo request
|
|
||||||
if (_summary != null && zoneId == _summary.zoneId) {
|
|
||||||
return _scdir.moveTo(sceneId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise, we make a zoned moveTo request; prepare to move to
|
|
||||||
// this scene (sets up pending data)
|
|
||||||
if (!_scdir.prepareMoveTo(sceneId, rl)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// let our zone observers know that we're attempting to switch
|
|
||||||
// zones
|
|
||||||
notifyObservers(Integer.valueOf(zoneId));
|
|
||||||
|
|
||||||
// check the version of our cached copy of the scene to which
|
|
||||||
// we're requesting to move; if we were unable to load it, assume
|
|
||||||
// a cached version of zero
|
|
||||||
int sceneVers = 0;
|
|
||||||
SceneModel pendingModel = _scdir.getPendingModel();
|
|
||||||
if (pendingModel != null) {
|
|
||||||
sceneVers = pendingModel.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// issue a moveTo request
|
|
||||||
Log.info("Issuing zoned moveTo(" + ZoneUtil.toString(zoneId) +
|
|
||||||
", " + sceneId + ", " + sceneVers + ").");
|
|
||||||
_zservice.moveTo(_ctx.getClient(), zoneId, sceneId, sceneVers, this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void fetchServices (Client client)
|
|
||||||
{
|
|
||||||
_zservice = (ZoneService)client.requireService(ZoneService.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void clientDidLogoff (Client client)
|
|
||||||
{
|
|
||||||
super.clientDidLogoff(client);
|
|
||||||
|
|
||||||
// clear out our business
|
|
||||||
_zservice = null;
|
|
||||||
_summary = null;
|
|
||||||
_previousZoneId = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called in response to a successful {@link ZoneService#moveTo}
|
|
||||||
* request.
|
|
||||||
*/
|
|
||||||
public void moveSucceeded (
|
|
||||||
int placeId, PlaceConfig config, ZoneSummary summary)
|
|
||||||
{
|
|
||||||
if (_summary != null) {
|
|
||||||
// keep track of our previous zone info
|
|
||||||
_previousZoneId = _summary.zoneId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// keep track of the summary
|
|
||||||
_summary = summary;
|
|
||||||
|
|
||||||
// pass the rest off to the standard scene transition code
|
|
||||||
_scdir.moveSucceeded(placeId, config);
|
|
||||||
|
|
||||||
// and let the zone observers know what's up
|
|
||||||
notifyObservers(summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called in response to a successful {@link ZoneService#moveTo}
|
|
||||||
* request when our cached scene was out of date and the server
|
|
||||||
* determined that we needed some updates.
|
|
||||||
*/
|
|
||||||
public void moveSucceededWithUpdates (
|
|
||||||
int placeId, PlaceConfig config, ZoneSummary summary,
|
|
||||||
SceneUpdate[] updates)
|
|
||||||
{
|
|
||||||
// keep track of the summary
|
|
||||||
_summary = summary;
|
|
||||||
|
|
||||||
// pass the rest off to the standard scene transition code
|
|
||||||
_scdir.moveSucceededWithUpdates(placeId, config, updates);
|
|
||||||
|
|
||||||
// and let the zone observers know what's up
|
|
||||||
notifyObservers(summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called in response to a successful {@link ZoneService#moveTo}
|
|
||||||
* request when our cached scene was out of date and the server
|
|
||||||
* determined that we needed an updated copy.
|
|
||||||
*/
|
|
||||||
public void moveSucceededWithScene (
|
|
||||||
int placeId, PlaceConfig config, ZoneSummary summary, SceneModel model)
|
|
||||||
{
|
|
||||||
// keep track of the summary
|
|
||||||
_summary = summary;
|
|
||||||
|
|
||||||
// pass the rest off to the standard scene transition code
|
|
||||||
_scdir.moveSucceededWithScene(placeId, config, model);
|
|
||||||
|
|
||||||
// and let the zone observers know what's up
|
|
||||||
notifyObservers(summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called in response to a failed zoned <code>moveTo</code> request.
|
|
||||||
*/
|
|
||||||
public void requestFailed (String reason)
|
|
||||||
{
|
|
||||||
// let the scene director cope
|
|
||||||
_scdir.requestFailed(reason);
|
|
||||||
|
|
||||||
// and let the observers know what's up
|
|
||||||
notifyObservers(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void forcedMove (int zoneId, int sceneId)
|
|
||||||
{
|
|
||||||
Log.info("Moving at request of server [zoneId=" + zoneId +
|
|
||||||
", sceneId=" + sceneId + "].");
|
|
||||||
|
|
||||||
// clear out our old scene and place data
|
|
||||||
_scdir.didLeaveScene();
|
|
||||||
|
|
||||||
// move to the new zone and scene
|
|
||||||
moveTo(zoneId, sceneId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when something breaks down after successfully completely a
|
|
||||||
* <code>moveTo</code> request.
|
|
||||||
*/
|
|
||||||
public void recoverMoveTo (int sceneId)
|
|
||||||
{
|
|
||||||
if (_previousZoneId != -1) {
|
|
||||||
moveTo(_previousZoneId, sceneId);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_scdir.moveTo(sceneId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies observers of success or failure, depending on the type of
|
|
||||||
* object provided as data.
|
|
||||||
*/
|
|
||||||
protected void notifyObservers (Object data)
|
|
||||||
{
|
|
||||||
// let our observers know that all is well on the western front
|
|
||||||
for (int i = 0; i < _observers.size(); i++) {
|
|
||||||
ZoneObserver obs = (ZoneObserver)_observers.get(i);
|
|
||||||
try {
|
|
||||||
if (data instanceof Integer) {
|
|
||||||
obs.zoneWillChange(((Integer)data).intValue());
|
|
||||||
} else if (data instanceof ZoneSummary) {
|
|
||||||
obs.zoneDidChange((ZoneSummary)data);
|
|
||||||
} else {
|
|
||||||
obs.zoneChangeFailed((String)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.warning("Zone observer choked during notification " +
|
|
||||||
"[data=" + data + ", obs=" + obs + "].");
|
|
||||||
Log.logStackTrace(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A reference to the active client context. */
|
|
||||||
protected WhirledContext _ctx;
|
|
||||||
|
|
||||||
/** A reference to the scene director with which we coordinate. */
|
|
||||||
protected SceneDirector _scdir;
|
|
||||||
|
|
||||||
/** Provides access to zone services. */
|
|
||||||
protected ZoneService _zservice;
|
|
||||||
|
|
||||||
/** A reference to the zone summary for the currently occupied
|
|
||||||
* zone. */
|
|
||||||
protected ZoneSummary _summary;
|
|
||||||
|
|
||||||
/** Our zone observer list. */
|
|
||||||
protected ArrayList _observers = new ArrayList();
|
|
||||||
|
|
||||||
/** Our previous zone id. */
|
|
||||||
protected int _previousZoneId = -1;
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.client;
|
|
||||||
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The zone observer interface makes it possible for entities to be
|
|
||||||
* notified when the client moves to a new zone.
|
|
||||||
*/
|
|
||||||
public interface ZoneObserver
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called when we begin the process of switching to a new zone. This
|
|
||||||
* will be followed by a call to {@link #zoneDidChange} to indicate
|
|
||||||
* that the change was successful or {@link #zoneChangeFailed} if the
|
|
||||||
* change fails.
|
|
||||||
*
|
|
||||||
* @param zoneId the zone id of the zone to which we are changing.
|
|
||||||
*/
|
|
||||||
public void zoneWillChange (int zoneId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when we have switched to a new zone.
|
|
||||||
*
|
|
||||||
* @param summary the summary information for the new zone or null if
|
|
||||||
* we have switched to no zone.
|
|
||||||
*/
|
|
||||||
public void zoneDidChange (ZoneSummary summary);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is called on all zone observers when a zone change request is
|
|
||||||
* rejected by the server or fails for some other reason.
|
|
||||||
*
|
|
||||||
* @param reason the reason code that explains why the zone change
|
|
||||||
* request was rejected or otherwise failed.
|
|
||||||
*/
|
|
||||||
public void zoneChangeFailed (String reason);
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.InvocationReceiver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines, for the zone services, a set of notifications delivered
|
|
||||||
* asynchronously by the server to the client.
|
|
||||||
*/
|
|
||||||
public interface ZoneReceiver extends InvocationReceiver
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Used to communicate a required move notification to the client. The
|
|
||||||
* server will have removed the client from their existing scene and
|
|
||||||
* the client is then responsible for generating a {@link
|
|
||||||
* ZoneService#moveTo} request to move to the new scene in the
|
|
||||||
* specified zone.
|
|
||||||
*/
|
|
||||||
public void forcedMove (int zoneId, int sceneId);
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.client.InvocationService;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the client interface to the zone related invocation services
|
|
||||||
* (e.g. moving between zones).
|
|
||||||
*/
|
|
||||||
public interface ZoneService extends InvocationService
|
|
||||||
{
|
|
||||||
/** Used to deliver responses to {@link #moveTo} requests. */
|
|
||||||
public static interface ZoneMoveListener extends InvocationListener
|
|
||||||
{
|
|
||||||
public void moveSucceeded (
|
|
||||||
int placeId, PlaceConfig config, ZoneSummary summary);
|
|
||||||
|
|
||||||
public void moveSucceededWithUpdates (
|
|
||||||
int placeId, PlaceConfig config, ZoneSummary summary,
|
|
||||||
SceneUpdate[] updates);
|
|
||||||
|
|
||||||
public void moveSucceededWithScene (
|
|
||||||
int placeId, PlaceConfig config, ZoneSummary summary,
|
|
||||||
SceneModel model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests that that this client's body be moved to the specified
|
|
||||||
* scene in the specified zone.
|
|
||||||
*
|
|
||||||
* @param zoneId the zone id to which we want to move.
|
|
||||||
* @param sceneId the scene id to which we want to move.
|
|
||||||
* @param version the version number of the scene object that we have
|
|
||||||
* in our local repository.
|
|
||||||
* @param listener the object that will receive the callback when the
|
|
||||||
* request succeeds or fails.
|
|
||||||
*/
|
|
||||||
public void moveTo (Client client, int zoneId, int sceneId,
|
|
||||||
int version, ZoneMoveListener listener);
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.data;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.threerings.io.Streamable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene summary class is used to provide info about the connected
|
|
||||||
* group of scenes that make up a zone. The group of scenes that make up a
|
|
||||||
* zone is a self-contained set of scenes, connected with one another (by
|
|
||||||
* portals) but not to any scenes outside the group.
|
|
||||||
*/
|
|
||||||
public class SceneSummary implements Streamable
|
|
||||||
{
|
|
||||||
/** The id of this scene. */
|
|
||||||
public int sceneId;
|
|
||||||
|
|
||||||
/** The name of this scene. */
|
|
||||||
public String name;
|
|
||||||
|
|
||||||
/** The ids of the scenes to which this scene is connected via
|
|
||||||
* portals. */
|
|
||||||
public int[] neighbors;
|
|
||||||
|
|
||||||
/** The directions in which each of the neighbors lay. */
|
|
||||||
public int[] neighborDirs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a string representation of this instance.
|
|
||||||
*/
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return "[sceneId=" + sceneId + ", name=" + name +
|
|
||||||
", neighbors=" + StringUtil.toString(neighbors) +
|
|
||||||
", neighborDirs=" + StringUtil.toString(neighborDirs) + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.data;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.SceneCodes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains codes used by the zone services.
|
|
||||||
*/
|
|
||||||
public interface ZoneCodes extends SceneCodes
|
|
||||||
{
|
|
||||||
/** An error code indicating that a zone identified by a particular
|
|
||||||
* zone id does not exist. Usually generated by a failed moveTo
|
|
||||||
* request. */
|
|
||||||
public static final String NO_SUCH_ZONE = "m.no_such_zone";
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.zone.data;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.zone.client.ZoneService;
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the implementation of the {@link ZoneService} interface
|
|
||||||
* that marshalls the arguments and delivers the request to the provider
|
|
||||||
* on the server. Also provides an implementation of the response listener
|
|
||||||
* interfaces that marshall the response arguments and deliver them back
|
|
||||||
* to the requesting client.
|
|
||||||
*/
|
|
||||||
public class ZoneMarshaller extends InvocationMarshaller
|
|
||||||
implements ZoneService
|
|
||||||
{
|
|
||||||
// documentation inherited
|
|
||||||
public static class ZoneMoveMarshaller extends ListenerMarshaller
|
|
||||||
implements ZoneMoveListener
|
|
||||||
{
|
|
||||||
/** The method id used to dispatch {@link #moveSucceeded}
|
|
||||||
* responses. */
|
|
||||||
public static final int MOVE_SUCCEEDED = 1;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceeded (int arg1, PlaceConfig arg2, ZoneSummary arg3)
|
|
||||||
{
|
|
||||||
_invId = null;
|
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
|
||||||
callerOid, requestId, MOVE_SUCCEEDED,
|
|
||||||
new Object[] { Integer.valueOf(arg1), arg2, arg3 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #moveSucceededWithScene}
|
|
||||||
* responses. */
|
|
||||||
public static final int MOVE_SUCCEEDED_WITH_SCENE = 2;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceededWithScene (int arg1, PlaceConfig arg2, ZoneSummary arg3, SceneModel arg4)
|
|
||||||
{
|
|
||||||
_invId = null;
|
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
|
||||||
callerOid, requestId, MOVE_SUCCEEDED_WITH_SCENE,
|
|
||||||
new Object[] { Integer.valueOf(arg1), arg2, arg3, arg4 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #moveSucceededWithUpdates}
|
|
||||||
* responses. */
|
|
||||||
public static final int MOVE_SUCCEEDED_WITH_UPDATES = 3;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveSucceededWithUpdates (int arg1, PlaceConfig arg2, ZoneSummary arg3, SceneUpdate[] arg4)
|
|
||||||
{
|
|
||||||
_invId = null;
|
|
||||||
omgr.postEvent(new InvocationResponseEvent(
|
|
||||||
callerOid, requestId, MOVE_SUCCEEDED_WITH_UPDATES,
|
|
||||||
new Object[] { Integer.valueOf(arg1), arg2, arg3, arg4 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchResponse (int methodId, Object[] args)
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case MOVE_SUCCEEDED:
|
|
||||||
((ZoneMoveListener)listener).moveSucceeded(
|
|
||||||
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (ZoneSummary)args[2]);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case MOVE_SUCCEEDED_WITH_SCENE:
|
|
||||||
((ZoneMoveListener)listener).moveSucceededWithScene(
|
|
||||||
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (ZoneSummary)args[2], (SceneModel)args[3]);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case MOVE_SUCCEEDED_WITH_UPDATES:
|
|
||||||
((ZoneMoveListener)listener).moveSucceededWithUpdates(
|
|
||||||
((Integer)args[0]).intValue(), (PlaceConfig)args[1], (ZoneSummary)args[2], (SceneUpdate[])args[3]);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchResponse(methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #moveTo} requests. */
|
|
||||||
public static final int MOVE_TO = 1;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void moveTo (Client arg1, int arg2, int arg3, int arg4, ZoneService.ZoneMoveListener arg5)
|
|
||||||
{
|
|
||||||
ZoneMarshaller.ZoneMoveMarshaller listener5 = new ZoneMarshaller.ZoneMoveMarshaller();
|
|
||||||
listener5.listener = arg5;
|
|
||||||
sendRequest(arg1, MOVE_TO, new Object[] {
|
|
||||||
Integer.valueOf(arg2), Integer.valueOf(arg3), Integer.valueOf(arg4), listener5
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.data;
|
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
|
||||||
|
|
||||||
import com.threerings.io.SimpleStreamableObject;
|
|
||||||
import com.threerings.util.Name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The zone summary contains information on a zone, including its name and
|
|
||||||
* summary info on all of the scenes in this zone (which can be used to
|
|
||||||
* generate a map of the zone on the client).
|
|
||||||
*/
|
|
||||||
public class ZoneSummary extends SimpleStreamableObject
|
|
||||||
{
|
|
||||||
/** The zone's fully qualified unique identifier. */
|
|
||||||
public int zoneId;
|
|
||||||
|
|
||||||
/** The name of the zone. */
|
|
||||||
public Name name;
|
|
||||||
|
|
||||||
/** The summary information for all of the scenes in the zone. */
|
|
||||||
public SceneSummary[] scenes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a string representation of this instance.
|
|
||||||
*/
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return "[zoneId=" + zoneId + ", name=" + name +
|
|
||||||
", scenes=" + StringUtil.toString(scenes) + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.data;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.ScenedBodyObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A system that uses the zone services must provide a body object
|
|
||||||
* extension that implements this interface.
|
|
||||||
*/
|
|
||||||
public interface ZonedBodyObject extends ScenedBodyObject
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns the zone id currently occupied by this body.
|
|
||||||
*/
|
|
||||||
public int getZoneId ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the zone id currently occupied by this body.
|
|
||||||
*/
|
|
||||||
public void setZoneId (int zoneId);
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.zone.server;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.server.InvocationDispatcher;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.zone.client.ZoneService;
|
|
||||||
import com.threerings.whirled.zone.data.ZoneMarshaller;
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches requests to the {@link ZoneProvider}.
|
|
||||||
*/
|
|
||||||
public class ZoneDispatcher extends InvocationDispatcher
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a dispatcher that may be registered to dispatch invocation
|
|
||||||
* service requests for the specified provider.
|
|
||||||
*/
|
|
||||||
public ZoneDispatcher (ZoneProvider provider)
|
|
||||||
{
|
|
||||||
this.provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public InvocationMarshaller createMarshaller ()
|
|
||||||
{
|
|
||||||
return new ZoneMarshaller();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchRequest (
|
|
||||||
ClientObject source, int methodId, Object[] args)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case ZoneMarshaller.MOVE_TO:
|
|
||||||
((ZoneProvider)provider).moveTo(
|
|
||||||
source,
|
|
||||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), ((Integer)args[2]).intValue(), (ZoneService.ZoneMoveListener)args[3]
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchRequest(source, methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.server;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.BodyObject;
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
import com.threerings.whirled.zone.data.ZonedBodyObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A zone is a collection of scenes organized into a connected group. A
|
|
||||||
* user can wander around within a zone, moving from scene to scene via
|
|
||||||
* the standard mechanisms. To move between zones, they must use a special
|
|
||||||
* mechanism (like at the dock, they can move from an island zone into
|
|
||||||
* their ship zone; or they can move from an island zone into their house
|
|
||||||
* zone). A zone provides scene summary information that can be used to
|
|
||||||
* display a map of the zone to the client.
|
|
||||||
*/
|
|
||||||
public interface ZoneManager
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Used to notify requesters when an asynchronous zone load has
|
|
||||||
* completed (successfully or not).
|
|
||||||
*/
|
|
||||||
public static interface ResolutionListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called when a zone was successfully resolved.
|
|
||||||
*/
|
|
||||||
public void zoneWasResolved (ZoneSummary summary);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a zone failed to resolve.
|
|
||||||
*/
|
|
||||||
public void zoneFailedToResolve (int zoneId, Exception reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves and delivers the scene summary information for the
|
|
||||||
* requested zone. Zone resolution is an asynchronous process, which
|
|
||||||
* necessitates this callback-style interface.
|
|
||||||
*
|
|
||||||
* @param zoneId the qualified zone id of the zone to resolve.
|
|
||||||
* @param listener the listener that should be notified when the zone
|
|
||||||
* is successfully resolved or is known to have failed to resolve.
|
|
||||||
*/
|
|
||||||
public void resolveZone (int zoneId, ResolutionListener listener);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a body has requested to leave a zone. The zone manager
|
|
||||||
* may return null to indicate that the body is allowed to leave the
|
|
||||||
* current zone or a string error code indicating the reason for
|
|
||||||
* denial of access (which will be propagated back to the requesting
|
|
||||||
* client).
|
|
||||||
*
|
|
||||||
* @param body the body object of the user that desires to depart
|
|
||||||
* their current zone (which can be obtained by casting the {@link
|
|
||||||
* BodyObject} to a {@link ZonedBodyObject}).
|
|
||||||
*/
|
|
||||||
public String ratifyBodyExit (BodyObject body);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a body has requested to enter a zone. The zone manager
|
|
||||||
* may return null to indicate that the body is allowed access to the
|
|
||||||
* zone or a string error code indicating the reason for denial of
|
|
||||||
* access (which will be propagated back to the requesting client).
|
|
||||||
* This method is called <em>after</em> the zone is resolved so that
|
|
||||||
* the zone manager may complete the ratification process without
|
|
||||||
* blocking (which it must do).
|
|
||||||
*
|
|
||||||
* @param body the body object of the user that desires access to the
|
|
||||||
* specified zone.
|
|
||||||
* @param zoneId the id of the zone to which the user desires access.
|
|
||||||
*/
|
|
||||||
public String ratifyBodyEntry (BodyObject body, int zoneId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a body has been granted access to a zone. This method
|
|
||||||
* must not block.
|
|
||||||
*
|
|
||||||
* @param body the body object of the user that was just granted
|
|
||||||
* access to a zone.
|
|
||||||
* @param zoneId the id of the zone to which they were granted access.
|
|
||||||
*/
|
|
||||||
public void bodyDidEnterZone (BodyObject body, int zoneId);
|
|
||||||
}
|
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.server;
|
|
||||||
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
import com.threerings.presents.server.InvocationProvider;
|
|
||||||
|
|
||||||
import com.threerings.crowd.data.BodyObject;
|
|
||||||
import com.threerings.crowd.data.PlaceConfig;
|
|
||||||
import com.threerings.crowd.data.PlaceObject;
|
|
||||||
import com.threerings.crowd.server.LocationProvider;
|
|
||||||
|
|
||||||
import com.threerings.whirled.data.SceneModel;
|
|
||||||
import com.threerings.whirled.data.SceneUpdate;
|
|
||||||
import com.threerings.whirled.data.ScenedBodyObject;
|
|
||||||
import com.threerings.whirled.server.SceneManager;
|
|
||||||
import com.threerings.whirled.server.SceneRegistry;
|
|
||||||
|
|
||||||
import com.threerings.whirled.zone.Log;
|
|
||||||
import com.threerings.whirled.zone.client.ZoneService.ZoneMoveListener;
|
|
||||||
import com.threerings.whirled.zone.data.ZoneCodes;
|
|
||||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
|
||||||
import com.threerings.whirled.zone.data.ZonedBodyObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides zone related services which are presently the ability to move
|
|
||||||
* from zone to zone.
|
|
||||||
*/
|
|
||||||
public class ZoneProvider
|
|
||||||
implements ZoneCodes, InvocationProvider
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Constructs a zone provider that will interoperate with the supplied
|
|
||||||
* zone and scene registries. The zone provider will automatically be
|
|
||||||
* constructed and registered by the {@link ZoneRegistry}, which a
|
|
||||||
* zone-using system must create and initialize in their server.
|
|
||||||
*/
|
|
||||||
public ZoneProvider (LocationProvider locprov, ZoneRegistry zonereg,
|
|
||||||
SceneRegistry screg)
|
|
||||||
{
|
|
||||||
_locprov = locprov;
|
|
||||||
_zonereg = zonereg;
|
|
||||||
_screg = screg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a request from a client to move to a scene in a new zone.
|
|
||||||
*
|
|
||||||
* @param caller the user requesting the move.
|
|
||||||
* @param zoneId the qualified zone id of the new zone.
|
|
||||||
* @param sceneId the identifier of the new scene.
|
|
||||||
* @param sceneVer the version of the scene model currently held by
|
|
||||||
* the client.
|
|
||||||
* @param listener the entity to inform of success or failure.
|
|
||||||
*/
|
|
||||||
public void moveTo (ClientObject caller, int zoneId, int sceneId,
|
|
||||||
int sceneVer, ZoneMoveListener listener)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
// avoid cluttering up the method declaration with final keywords
|
|
||||||
final BodyObject fsource = (BodyObject)caller;
|
|
||||||
final int fsceneId = sceneId;
|
|
||||||
final int fsceneVer = sceneVer;
|
|
||||||
final ZoneMoveListener flistener = listener;
|
|
||||||
|
|
||||||
// look up the caller's current zone id and make sure it is happy
|
|
||||||
// about their departure from the current zone
|
|
||||||
if (!(caller instanceof ZonedBodyObject)) {
|
|
||||||
Log.warning("Request to switch zones by non-ZonedBodyObject!? " +
|
|
||||||
"[clobj=" + caller.getClass() + "].");
|
|
||||||
throw new InvocationException(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
ZonedBodyObject zcaller = (ZonedBodyObject)caller;
|
|
||||||
ZoneManager ozmgr = _zonereg.getZoneManager(zcaller.getZoneId());
|
|
||||||
if (ozmgr != null) {
|
|
||||||
String msg = ozmgr.ratifyBodyExit(fsource);
|
|
||||||
if (msg != null) {
|
|
||||||
throw new InvocationException(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// look up the zone manager for the zone
|
|
||||||
ZoneManager zmgr = _zonereg.getZoneManager(zoneId);
|
|
||||||
if (zmgr == null) {
|
|
||||||
Log.warning("Requested to enter a zone for which we have no " +
|
|
||||||
"manager [user=" + fsource.who() +
|
|
||||||
", zoneId=" + zoneId + "].");
|
|
||||||
throw new InvocationException(NO_SUCH_ZONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve the zone!
|
|
||||||
ZoneManager.ResolutionListener zl = new ZoneManager.ResolutionListener()
|
|
||||||
{
|
|
||||||
public void zoneWasResolved (ZoneSummary summary) {
|
|
||||||
continueMoveTo(
|
|
||||||
fsource, summary, fsceneId, fsceneVer, flistener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void zoneFailedToResolve (int zoneId, Exception reason) {
|
|
||||||
Log.warning("Unable to resolve zone [zoneId=" + zoneId +
|
|
||||||
", reason=" + reason + "].");
|
|
||||||
flistener.requestFailed(NO_SUCH_ZONE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
zmgr.resolveZone(zoneId, zl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is called after we have resolved our zone.
|
|
||||||
*/
|
|
||||||
protected void continueMoveTo (
|
|
||||||
BodyObject source, ZoneSummary summary, int sceneId, int sceneVer,
|
|
||||||
ZoneMoveListener listener)
|
|
||||||
{
|
|
||||||
// avoid cluttering up the method declaration with final keywords
|
|
||||||
final BodyObject fsource = source;
|
|
||||||
final ZoneSummary fsum = summary;
|
|
||||||
final int fsceneVer = sceneVer;
|
|
||||||
final ZoneMoveListener flistener = listener;
|
|
||||||
|
|
||||||
// give the zone manager a chance to veto the request
|
|
||||||
ZoneManager zmgr = _zonereg.getZoneManager(summary.zoneId);
|
|
||||||
String errmsg = zmgr.ratifyBodyEntry(source, summary.zoneId);
|
|
||||||
if (errmsg != null) {
|
|
||||||
listener.requestFailed(errmsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a callback object that will handle the resolution or
|
|
||||||
// failed resolution of the scene
|
|
||||||
SceneRegistry.ResolutionListener rl = null;
|
|
||||||
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 zone move, client gone " +
|
|
||||||
"[who=" + fsource.who() +
|
|
||||||
", dest=" + scmgr.where() + "].");
|
|
||||||
// No one to respond to, just mark that we're okay with it.
|
|
||||||
InvocationMarshaller.setNoResponse(flistener);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
finishMoveTo(fsource, fsum, scmgr, fsceneVer, flistener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sceneFailedToResolve (int sceneId, Exception reason) {
|
|
||||||
Log.warning("Unable to resolve scene [sceneid=" + sceneId +
|
|
||||||
", reason=" + reason + "].");
|
|
||||||
// pretend like the scene doesn't exist to the client
|
|
||||||
flistener.requestFailed(NO_SUCH_PLACE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// make sure the scene they are headed to is actually loaded into
|
|
||||||
// the server
|
|
||||||
_screg.resolveScene(sceneId, rl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is called after the scene to which we are moving is guaranteed
|
|
||||||
* to have been loaded into the server.
|
|
||||||
*/
|
|
||||||
protected void finishMoveTo (
|
|
||||||
BodyObject source, ZoneSummary summary, SceneManager scmgr,
|
|
||||||
int sceneVersion, ZoneMoveListener listener)
|
|
||||||
{
|
|
||||||
// move to the place object associated with this scene
|
|
||||||
PlaceObject plobj = scmgr.getPlaceObject();
|
|
||||||
int ploid = plobj.getOid();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// try doing the actual move
|
|
||||||
PlaceConfig config = _locprov.moveTo(source, ploid);
|
|
||||||
|
|
||||||
// now that we've finally moved, we can update the user object
|
|
||||||
// with the new scene and zone ids
|
|
||||||
source.startTransaction();
|
|
||||||
try {
|
|
||||||
((ScenedBodyObject)source).setSceneId(scmgr.getScene().getId());
|
|
||||||
((ZonedBodyObject)source).setZoneId(summary.zoneId);
|
|
||||||
} finally {
|
|
||||||
source.commitTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if they need a newer version of the scene data
|
|
||||||
SceneModel model = scmgr.getScene().getSceneModel();
|
|
||||||
if (sceneVersion < model.version) {
|
|
||||||
SceneUpdate[] updates = scmgr.getUpdates(sceneVersion);
|
|
||||||
if (updates != null) {
|
|
||||||
listener.moveSucceededWithUpdates(
|
|
||||||
ploid, config, summary, updates);
|
|
||||||
} else {
|
|
||||||
listener.moveSucceededWithScene(
|
|
||||||
ploid, config, summary, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// then send the moveTo response
|
|
||||||
listener.moveSucceeded(ploid, config, summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
// let the zone manager know that someone just came on in
|
|
||||||
ZoneManager zmgr = _zonereg.getZoneManager(summary.zoneId);
|
|
||||||
zmgr.bodyDidEnterZone(source, summary.zoneId);
|
|
||||||
|
|
||||||
} catch (InvocationException ie) {
|
|
||||||
listener.requestFailed(ie.getMessage());
|
|
||||||
|
|
||||||
} catch (RuntimeException re) {
|
|
||||||
Log.logStackTrace(re);
|
|
||||||
listener.requestFailed(INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ejects the specified body from their current scene and sends them a
|
|
||||||
* request to move to the specified new zone and scene. This is the
|
|
||||||
* zone-equivalent to {@link LocationProvider#moveBody}.
|
|
||||||
*
|
|
||||||
* @return null if the user was forcibly moved, or a string indicating
|
|
||||||
* the reason for denial of departure of their current zone (from
|
|
||||||
* {@link ZoneManager#ratifyBodyExit}).
|
|
||||||
*/
|
|
||||||
public String moveBody (ZonedBodyObject source, int zoneId, int sceneId)
|
|
||||||
{
|
|
||||||
if (source.getZoneId() == zoneId) {
|
|
||||||
// handle the case of moving somewhere in the same zone
|
|
||||||
_screg.sceneprov.moveBody((BodyObject) source, sceneId);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// first remove them from their old location
|
|
||||||
String reason = leaveOccupiedZone(source);
|
|
||||||
if (reason != null) {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
// then send a forced move notification
|
|
||||||
ZoneSender.forcedMove((BodyObject)source, zoneId, sceneId);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ejects the specified body from their current scene and zone. This
|
|
||||||
* is the zone equivalent to {@link
|
|
||||||
* LocationProvider#leaveOccupiedPlace}.
|
|
||||||
*
|
|
||||||
* @return null if the user was forcibly moved, or a string indicating
|
|
||||||
* the reason for denial of departure of their current zone (from
|
|
||||||
* {@link ZoneManager#ratifyBodyExit}).
|
|
||||||
*/
|
|
||||||
public String leaveOccupiedZone (ZonedBodyObject source)
|
|
||||||
{
|
|
||||||
// look up the caller's current zone id and make sure it is happy
|
|
||||||
// about their departure from the current zone
|
|
||||||
ZoneManager zmgr = _zonereg.getZoneManager(source.getZoneId());
|
|
||||||
String msg;
|
|
||||||
if (zmgr != null &&
|
|
||||||
(msg = zmgr.ratifyBodyExit((BodyObject)source)) != null) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove them from their occupied scene
|
|
||||||
_screg.sceneprov.leaveOccupiedScene(source);
|
|
||||||
|
|
||||||
// and clear out their zone information
|
|
||||||
source.setZoneId(-1);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The entity that handles basic location changes. */
|
|
||||||
protected LocationProvider _locprov;
|
|
||||||
|
|
||||||
/** The zone registry with which we communicate. */
|
|
||||||
protected ZoneRegistry _zonereg;
|
|
||||||
|
|
||||||
/** The scene registry with which we communicate. */
|
|
||||||
protected SceneRegistry _screg;
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.server;
|
|
||||||
|
|
||||||
import com.samskivert.util.HashIntMap;
|
|
||||||
|
|
||||||
import com.threerings.presents.server.InvocationManager;
|
|
||||||
|
|
||||||
import com.threerings.crowd.server.PlaceRegistry;
|
|
||||||
import com.threerings.whirled.server.SceneRegistry;
|
|
||||||
|
|
||||||
import com.threerings.whirled.zone.Log;
|
|
||||||
import com.threerings.whirled.zone.util.ZoneUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The zone registry takes care of mapping zone requests to the
|
|
||||||
* appropriate registered zone manager.
|
|
||||||
*/
|
|
||||||
public class ZoneRegistry
|
|
||||||
{
|
|
||||||
/** Implements the server-side of the zone-related services. */
|
|
||||||
public ZoneProvider zoneprov;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a zone manager with the supplied configuration.
|
|
||||||
*/
|
|
||||||
public ZoneRegistry (InvocationManager invmgr, PlaceRegistry plreg,
|
|
||||||
SceneRegistry screg)
|
|
||||||
{
|
|
||||||
// create a zone provider and register it with the invocation
|
|
||||||
// services
|
|
||||||
zoneprov = new ZoneProvider(plreg.locprov, this, screg);
|
|
||||||
invmgr.registerDispatcher(new ZoneDispatcher(zoneprov), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the supplied zone manager as the manager for the
|
|
||||||
* specified zone type. Zone types are 7 bits and managers are
|
|
||||||
* responsible for making sure they don't use a zone type that
|
|
||||||
* collides with another manager (given that we have only three zone
|
|
||||||
* types at present, this doesn't seem unreasonable).
|
|
||||||
*/
|
|
||||||
public void registerZoneManager (byte zoneType, ZoneManager manager)
|
|
||||||
{
|
|
||||||
ZoneManager old = (ZoneManager)_managers.get(zoneType);
|
|
||||||
if (old != null) {
|
|
||||||
Log.warning("Zone manager already registered with requested " +
|
|
||||||
"type [type=" + zoneType + ", old=" + old +
|
|
||||||
", new=" + manager + "].");
|
|
||||||
} else {
|
|
||||||
_managers.put(zoneType, manager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the zone manager that handles the specified zone id.
|
|
||||||
*
|
|
||||||
* @param qualifiedZoneId the qualified zone id for which the manager
|
|
||||||
* should be looked up.
|
|
||||||
*/
|
|
||||||
public ZoneManager getZoneManager (int qualifiedZoneId)
|
|
||||||
{
|
|
||||||
int zoneType = ZoneUtil.zoneType(qualifiedZoneId);
|
|
||||||
return (ZoneManager)_managers.get(zoneType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A table of zone managers. */
|
|
||||||
protected HashIntMap _managers = new HashIntMap();
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//
|
|
||||||
// $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.whirled.zone.server;
|
|
||||||
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.server.InvocationSender;
|
|
||||||
import com.threerings.whirled.zone.client.ZoneDecoder;
|
|
||||||
import com.threerings.whirled.zone.client.ZoneReceiver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to issue notifications to a {@link ZoneReceiver} instance on a
|
|
||||||
* client.
|
|
||||||
*/
|
|
||||||
public class ZoneSender extends InvocationSender
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Issues a notification that will result in a call to {@link
|
|
||||||
* ZoneReceiver#forcedMove} on a client.
|
|
||||||
*/
|
|
||||||
public static void forcedMove (
|
|
||||||
ClientObject target, int arg1, int arg2)
|
|
||||||
{
|
|
||||||
sendNotification(
|
|
||||||
target, ZoneDecoder.RECEIVER_CODE, ZoneDecoder.FORCED_MOVE,
|
|
||||||
new Object[] { Integer.valueOf(arg1), Integer.valueOf(arg2) });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 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.whirled.zone.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server-specific, zone-related utility functions.
|
|
||||||
*/
|
|
||||||
public class ZoneUtil
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Composes the zone type and zone id into a qualified zone id. A
|
|
||||||
* qualified zone id is what should be passed around so that the
|
|
||||||
* server can determine the zone type from the zone id when necessary.
|
|
||||||
*/
|
|
||||||
public static int qualifyZoneId (byte zoneType, int zoneId)
|
|
||||||
{
|
|
||||||
int qualifiedZoneId = zoneType;
|
|
||||||
qualifiedZoneId <<= 24;
|
|
||||||
qualifiedZoneId |= zoneId;
|
|
||||||
return qualifiedZoneId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the zone type from a qualified zone id.
|
|
||||||
*/
|
|
||||||
public static int zoneType (int qualifiedZoneId)
|
|
||||||
{
|
|
||||||
return (0xFF000000 & qualifiedZoneId) >> 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the zone id from a qualified zone id.
|
|
||||||
*/
|
|
||||||
public static int zoneId (int qualifiedZoneId)
|
|
||||||
{
|
|
||||||
return (0x00FFFFFF & qualifiedZoneId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an easier to read representation of the supplied qualified
|
|
||||||
* zone id: <code>type:id</code>.
|
|
||||||
*/
|
|
||||||
public static String toString (int qualifiedZoneId)
|
|
||||||
{
|
|
||||||
return zoneType(qualifiedZoneId) + ":" + zoneId(qualifiedZoneId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user