Behold Vilya, Ring of Air and repository for our game and virtual worldly
extensions to the distributed environment provided by Narya. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@1 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// $Id: SceneDispatcher.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
//
|
||||
// $Id: SceneManager.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
//
|
||||
// $Id: SceneProvider.java 3832 2006-02-04 03:49:53Z ray $
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
//
|
||||
// $Id: SceneRegistry.java 3679 2005-08-11 22:30:40Z ray $
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// $Id: SceneSender.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// 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) });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// $Id: WhirledClient.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// $Id: WhirledServer.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// $Id: DummySceneRepository.java 3438 2005-03-29 23:18:59Z mdb $
|
||||
//
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// $Id: SceneRepository.java 3438 2005-03-29 23:18:59Z mdb $
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user