Files
narya/src/java/com/threerings/whirled/server/SceneManager.java
T
Ray Greenwell 79c6427c21 StringBuffer -> StringBuilder.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4191 542714f4-19e9-0310-aa3c-eee0fc999fb1
2006-06-13 22:42:20 +00:00

195 lines
6.7 KiB
Java

//
// $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;
}