diff --git a/build.xml b/build.xml index a54bfd4af..e77907a04 100644 --- a/build.xml +++ b/build.xml @@ -71,7 +71,6 @@ - diff --git a/src/java/com/threerings/crowd/server/CrowdClient.java b/src/java/com/threerings/crowd/server/CrowdClient.java index 6785d2011..7b0e26981 100644 --- a/src/java/com/threerings/crowd/server/CrowdClient.java +++ b/src/java/com/threerings/crowd/server/CrowdClient.java @@ -84,6 +84,6 @@ public class CrowdClient extends PresentsClient */ protected void clearLocation (BodyObject bobj) { - CrowdServer.plreg.locprov.leaveOccupiedPlace(bobj); + CrowdServer.locman.leaveOccupiedPlace(bobj); } } diff --git a/src/java/com/threerings/crowd/server/CrowdServer.java b/src/java/com/threerings/crowd/server/CrowdServer.java index 584422075..21d4b66c3 100644 --- a/src/java/com/threerings/crowd/server/CrowdServer.java +++ b/src/java/com/threerings/crowd/server/CrowdServer.java @@ -67,6 +67,9 @@ public class CrowdServer extends PresentsServer /** Our body manager. */ public static BodyManager bodyman; + /** Our location manager. */ + public static LocationManager locman; + /** * Initializes all of the server services and prepares for operation. */ @@ -79,6 +82,7 @@ public class CrowdServer extends PresentsServer plreg = _plreg; chatprov = _chatprov; bodyman = _bodyman; + locman = _locman; // configure the client manager to use our bits clmgr.setClientFactory(new ClientFactory() { @@ -90,6 +94,9 @@ public class CrowdServer extends PresentsServer } }); + // configure the place registry with the injector + _plreg.setInjector(injector); + // create our body locator _lookup = createBodyLocator(); } @@ -155,6 +162,9 @@ public class CrowdServer extends PresentsServer /** Handles body-related invocation services. */ @Inject protected BodyManager _bodyman; + /** Handles location-related invocation services. */ + @Inject protected LocationManager _locman; + /** Provides chat-related invocation services. */ @Inject protected ChatProvider _chatprov; diff --git a/src/java/com/threerings/crowd/server/LocationManager.java b/src/java/com/threerings/crowd/server/LocationManager.java new file mode 100644 index 000000000..78ce16a98 --- /dev/null +++ b/src/java/com/threerings/crowd/server/LocationManager.java @@ -0,0 +1,223 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2008 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.server; + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import com.threerings.presents.data.ClientObject; +import com.threerings.presents.dobj.RootDObjectManager; + +import com.threerings.presents.server.ClientManager; +import com.threerings.presents.server.InvocationException; +import com.threerings.presents.server.InvocationManager; +import com.threerings.presents.server.InvocationProvider; +import com.threerings.presents.server.PresentsClient; + +import com.threerings.crowd.client.LocationService; +import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.CrowdCodes; +import com.threerings.crowd.data.LocationCodes; +import com.threerings.crowd.data.Place; +import com.threerings.crowd.data.PlaceConfig; +import com.threerings.crowd.data.PlaceObject; +import com.threerings.crowd.server.CrowdServer; + +import static com.threerings.crowd.Log.log; + +/** + * Handles location-related services. + */ +@Singleton +public class LocationManager + implements LocationProvider, LocationCodes +{ + @Inject public LocationManager (InvocationManager invmgr) + { + invmgr.registerDispatcher(new LocationDispatcher(this), CrowdCodes.CROWD_GROUP); + } + + // from interface LocationProvider + public void moveTo (ClientObject caller, int placeOid, LocationService.MoveListener listener) + throws InvocationException + { + // do the move and send the response + listener.moveSucceeded(moveTo((BodyObject)caller, placeOid)); + } + + // from interface LocationProvider + public void leavePlace (ClientObject caller) + { + leaveOccupiedPlace((BodyObject)caller); + } + + /** + * Moves the specified body from whatever location they currently occupy to the location + * identified by the supplied place oid. + * + * @return the config object for the new location. + * + * @exception ServiceFaildException thrown if the move was not successful for some reason + * (which will be communicated as an error code in the exception's message data). + */ + public PlaceConfig moveTo (BodyObject source, int placeOid) + throws InvocationException + { + int bodoid = source.getOid(); + + // make sure the place in question actually exists + PlaceManager pmgr = _plreg.getPlaceManager(placeOid); + if (pmgr == null) { + log.info("Requested to move to non-existent place [who=" + source.who() + + ", placeOid=" + placeOid + "]."); + throw new InvocationException(NO_SUCH_PLACE); + } + + // if they're already in the location they're asking to move to, just give them the config + // because we don't need to update anything in distributed object world + Place place = pmgr.getLocation(); + if (place.equals(source.location)) { + log.debug("Going along with client request to move to where they already are " + + "[source=" + source.who() + ", place=" + place + "]."); + return pmgr.getConfig(); + } + + // make sure they have access to the specified place + String errmsg; + if ((errmsg = pmgr.ratifyBodyEntry(source)) != null) { + throw new InvocationException(errmsg); + } + + // acquire a lock on the body object to avoid breakage by rapid fire moveTo requests + if (!source.acquireLock("moveToLock")) { + // if we're still locked, a previous moveTo request hasn't been fully processed + throw new InvocationException(MOVE_IN_PROGRESS); + } + + // configure the client accordingly if the place uses a custom class loader + PresentsClient client = _clmgr.getClient(source.username); + if (client != null) { + client.setClassLoader(pmgr.getClass().getClassLoader()); + } + + try { + PlaceObject plobj = pmgr.getPlaceObject(); + + // the doubly nested try catch is to prevent failure if one or the other of the + // transactions fails to start + plobj.startTransaction(); + try { + source.startTransaction(); + try { + // remove them from any previous location + leaveOccupiedPlace(source); + + // generate a new occinfo record (which will add it to the target location) + pmgr.buildOccupantInfo(source); + + // set the body's new location + source.willEnterPlace(place, plobj); + + // add the body oid to the place object's occupant list + plobj.addToOccupants(bodoid); + + } finally { + source.commitTransaction(); + } + } finally { + plobj.commitTransaction(); + } + + } finally { + // and finally queue up an event to release the lock once these events are processed + source.releaseLock("moveToLock"); + } + + return pmgr.getConfig(); + } + + /** + * Removes the specified body from the place object they currently occupy. Does nothing if the + * body is not currently in a place. + */ + public void leaveOccupiedPlace (BodyObject source) + { + Place oldloc = source.location; + int bodoid = source.getOid(); + + // nothing to do if they weren't previously in some location + if (oldloc == null) { + return; + } + + // remove them from the occupant list + PlaceObject plobj = null; + try { + plobj = (PlaceObject)_omgr.getObject(oldloc.placeOid); + if (plobj != null) { + Integer key = Integer.valueOf(bodoid); + plobj.startTransaction(); + try { + // remove their occupant info (which is keyed on oid) + plobj.removeFromOccupantInfo(key); + // and remove them from the occupant list + plobj.removeFromOccupants(bodoid); + + } finally { + plobj.commitTransaction(); + } + + } else { + log.info("Body's prior location no longer around? [boid=" + bodoid + + ", place=" + oldloc + "]."); + } + + } catch (ClassCastException cce) { + log.warning("Body claims to occupy non-PlaceObject!? [boid=" + bodoid + + ", place=" + oldloc + ", error=" + cce + "]."); + } + + // clear out their location + source.didLeavePlace(plobj); + } + + /** + * Forcibly moves the specified body object to the new place. This is accomplished by first + * removing the client from their old location and then sending the client a notification, + * instructing it to move to the new location (which it does using the normal moveTo service). + * This has the benefit that the client is removed from their old place regardless of whether + * or not they are cooperating. If they choose to ignore the forced move request, they will + * remain in limbo, unable to do much of anything. + */ + public void moveBody (BodyObject source, Place place) + { + // first remove them from their old place + leaveOccupiedPlace(source); + + // then send a forced move notification + LocationSender.forcedMove(source, place.placeOid); + } + + @Inject protected RootDObjectManager _omgr; + @Inject protected PlaceRegistry _plreg; + @Inject protected ClientManager _clmgr; +} diff --git a/src/java/com/threerings/crowd/server/LocationProvider.java b/src/java/com/threerings/crowd/server/LocationProvider.java index e91acd649..ec04bd4fd 100644 --- a/src/java/com/threerings/crowd/server/LocationProvider.java +++ b/src/java/com/threerings/crowd/server/LocationProvider.java @@ -2,7 +2,7 @@ // $Id$ // // Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// Copyright (C) 2002-2008 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 @@ -21,218 +21,24 @@ package com.threerings.crowd.server; -import com.threerings.presents.dobj.RootDObjectManager; - -import com.threerings.presents.data.ClientObject; - -import com.threerings.presents.server.InvocationException; -import com.threerings.presents.server.InvocationManager; -import com.threerings.presents.server.InvocationProvider; -import com.threerings.presents.server.PresentsClient; - import com.threerings.crowd.client.LocationService; -import com.threerings.crowd.data.BodyObject; -import com.threerings.crowd.data.LocationCodes; -import com.threerings.crowd.data.Place; -import com.threerings.crowd.data.PlaceConfig; -import com.threerings.crowd.data.PlaceObject; -import com.threerings.crowd.server.CrowdServer; - -import static com.threerings.crowd.Log.log; +import com.threerings.presents.data.ClientObject; +import com.threerings.presents.server.InvocationException; +import com.threerings.presents.server.InvocationProvider; /** - * This class provides the server end of the location services. + * Defines the server-side of the {@link LocationService}. */ -public class LocationProvider - implements LocationCodes, InvocationProvider +public interface LocationProvider extends InvocationProvider { /** - * Creates a location provider and prepares it for operation. + * Handles a {@link LocationService#leavePlace} request. */ - public LocationProvider (InvocationManager invmgr, RootDObjectManager omgr, PlaceRegistry plreg) - { - // we'll need these later - _invmgr = invmgr; - _omgr = omgr; - _plreg = plreg; - } + public void leavePlace (ClientObject caller); /** - * Requests that this client's body be moved to the specified location. - * - * @param caller the client object of the client that invoked this remotely callable method. - * @param place the oid of the place to which the body should be moved. - * @param listener the listener that will be informed of success or failure. + * Handles a {@link LocationService#moveTo} request. */ - public void moveTo (ClientObject caller, int placeOid, LocationService.MoveListener listener) - throws InvocationException - { - // do the move and send the response - listener.moveSucceeded(moveTo((BodyObject)caller, placeOid)); - } - - /** - * Requests that we leave our current place and move to nowhere land. - */ - public void leavePlace (ClientObject caller) - throws InvocationException - { - leaveOccupiedPlace((BodyObject)caller); - } - - /** - * Moves the specified body from whatever location they currently occupy to the location - * identified by the supplied place oid. - * - * @return the config object for the new location. - * - * @exception ServiceFaildException thrown if the move was not successful for some reason - * (which will be communicated as an error code in the exception's message data). - */ - public PlaceConfig moveTo (BodyObject source, int placeOid) - throws InvocationException - { - int bodoid = source.getOid(); - - // make sure the place in question actually exists - PlaceManager pmgr = _plreg.getPlaceManager(placeOid); - if (pmgr == null) { - log.info("Requested to move to non-existent place [who=" + source.who() + - ", placeOid=" + placeOid + "]."); - throw new InvocationException(NO_SUCH_PLACE); - } - - // if they're already in the location they're asking to move to, just give them the config - // because we don't need to update anything in distributed object world - Place place = pmgr.getLocation(); - if (place.equals(source.location)) { - log.debug("Going along with client request to move to where they already are " + - "[source=" + source.who() + ", place=" + place + "]."); - return pmgr.getConfig(); - } - - // make sure they have access to the specified place - String errmsg; - if ((errmsg = pmgr.ratifyBodyEntry(source)) != null) { - throw new InvocationException(errmsg); - } - - // acquire a lock on the body object to avoid breakage by rapid fire moveTo requests - if (!source.acquireLock("moveToLock")) { - // if we're still locked, a previous moveTo request hasn't been fully processed - throw new InvocationException(MOVE_IN_PROGRESS); - } - - // configure the client accordingly if the place uses a custom class loader - PresentsClient client = CrowdServer.clmgr.getClient(source.username); - if (client != null) { - client.setClassLoader(_plreg.getClassLoader(pmgr.getConfig())); - } - - try { - PlaceObject plobj = pmgr.getPlaceObject(); - - // the doubly nested try catch is to prevent failure if one or the other of the - // transactions fails to start - plobj.startTransaction(); - try { - source.startTransaction(); - try { - // remove them from any previous location - leaveOccupiedPlace(source); - - // generate a new occinfo record (which will add it to the target location) - pmgr.buildOccupantInfo(source); - - // set the body's new location - source.willEnterPlace(place, plobj); - - // add the body oid to the place object's occupant list - plobj.addToOccupants(bodoid); - - } finally { - source.commitTransaction(); - } - } finally { - plobj.commitTransaction(); - } - - } finally { - // and finally queue up an event to release the lock once these events are processed - source.releaseLock("moveToLock"); - } - - return pmgr.getConfig(); - } - - /** - * Removes the specified body from the place object they currently occupy. Does nothing if the - * body is not currently in a place. - */ - public void leaveOccupiedPlace (BodyObject source) - { - Place oldloc = source.location; - int bodoid = source.getOid(); - - // nothing to do if they weren't previously in some location - if (oldloc == null) { - return; - } - - // remove them from the occupant list - PlaceObject plobj = null; - try { - plobj = (PlaceObject)_omgr.getObject(oldloc.placeOid); - if (plobj != null) { - Integer key = Integer.valueOf(bodoid); - plobj.startTransaction(); - try { - // remove their occupant info (which is keyed on oid) - plobj.removeFromOccupantInfo(key); - // and remove them from the occupant list - plobj.removeFromOccupants(bodoid); - - } finally { - plobj.commitTransaction(); - } - - } else { - log.info("Body's prior location no longer around? [boid=" + bodoid + - ", place=" + oldloc + "]."); - } - - } catch (ClassCastException cce) { - log.warning("Body claims to occupy non-PlaceObject!? [boid=" + bodoid + - ", place=" + oldloc + ", error=" + cce + "]."); - } - - // clear out their location - source.didLeavePlace(plobj); - } - - /** - * Forcibly moves the specified body object to the new place. This is accomplished by first - * removing the client from their old location and then sending the client a notification, - * instructing it to move to the new location (which it does using the normal moveTo service). - * This has the benefit that the client is removed from their old place regardless of whether - * or not they are cooperating. If they choose to ignore the forced move request, they will - * remain in limbo, unable to do much of anything. - */ - public void moveBody (BodyObject source, Place place) - { - // first remove them from their old place - leaveOccupiedPlace(source); - - // then send a forced move notification - LocationSender.forcedMove(source, place.placeOid); - } - - /** The invocation manager with which we interoperate. */ - protected InvocationManager _invmgr; - - /** The distributed object manager with which we interoperate. */ - protected RootDObjectManager _omgr; - - /** The place registry with which we interoperate. */ - protected PlaceRegistry _plreg; + public void moveTo (ClientObject caller, int arg1, LocationService.MoveListener arg2) + throws InvocationException; } diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index 651fcbfdc..b729781b4 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -36,7 +36,6 @@ import com.samskivert.util.StringUtil; import com.threerings.presents.data.ClientObject; import com.threerings.presents.dobj.AccessController; import com.threerings.presents.dobj.DObject; -import com.threerings.presents.dobj.DObjectManager; import com.threerings.presents.dobj.DynamicListener; import com.threerings.presents.dobj.EntryUpdatedEvent; import com.threerings.presents.dobj.MessageEvent; @@ -46,9 +45,9 @@ import com.threerings.presents.dobj.ObjectDeathListener; import com.threerings.presents.dobj.ObjectDestroyedEvent; import com.threerings.presents.dobj.ObjectRemovedEvent; import com.threerings.presents.dobj.OidListListener; +import com.threerings.presents.dobj.RootDObjectManager; import com.threerings.presents.dobj.SetAdapter; import com.threerings.presents.server.InvocationManager; -import com.threerings.presents.server.PresentsDObjectMgr; import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.OccupantInfo; @@ -168,8 +167,7 @@ public class PlaceManager { // update the canonical copy _occInfo.put(occInfo.getBodyOid(), occInfo); - // clone the canonical copy and send out an event updating the distributed set with that - // clone + // clone the canonical copy and send an event updating the distributed set with that clone _plobj.updateOccupantInfo((OccupantInfo)occInfo.clone()); } @@ -177,7 +175,7 @@ public class PlaceManager * Called by the place registry after creating this place manager. */ public void init (PlaceRegistry registry, InvocationManager invmgr, - DObjectManager omgr, PlaceConfig config) + RootDObjectManager omgr, PlaceConfig config) { _registry = registry; _invmgr = invmgr; @@ -263,7 +261,7 @@ public class PlaceManager public void shutdown () { // destroy the object and everything will follow from that - CrowdServer.omgr.destroyObject(_plobj.getOid()); + _omgr.destroyObject(_plobj.getOid()); // clear out our services if (_plobj.speakService != null) { @@ -349,7 +347,7 @@ public class PlaceManager // the first argument should be the client object of the caller or null if it is // a server-originated event int srcoid = event.getSourceOid(); - DObject source = (srcoid <= 0) ? null : CrowdServer.omgr.getObject(srcoid); + DObject source = (srcoid <= 0) ? null : _omgr.getObject(srcoid); Object[] args = event.getArgs(), nargs; if (args == null) { nargs = new Object[] { source }; @@ -636,7 +634,7 @@ public class PlaceManager // queue up a shutdown interval, unless we've already got one. long idlePeriod = idleUnloadPeriod(); if (idlePeriod > 0L && _shutdownInterval == null) { - _shutdownInterval = new Interval((PresentsDObjectMgr)_omgr) { + _shutdownInterval = new Interval(_omgr) { public void expired () { log.debug("Unloading idle place '" + where () + "'."); shutdown(); @@ -693,7 +691,7 @@ public class PlaceManager protected InvocationManager _invmgr; /** A distributed object manager for doing dobj stuff. */ - protected DObjectManager _omgr; + protected RootDObjectManager _omgr; /** A reference to the place object that we manage. */ protected PlaceObject _plobj; diff --git a/src/java/com/threerings/crowd/server/PlaceRegistry.java b/src/java/com/threerings/crowd/server/PlaceRegistry.java index c261fa9ff..4eec0f31b 100644 --- a/src/java/com/threerings/crowd/server/PlaceRegistry.java +++ b/src/java/com/threerings/crowd/server/PlaceRegistry.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import com.google.inject.Inject; +import com.google.inject.Injector; import com.google.inject.Singleton; import com.samskivert.util.IntMap; @@ -57,39 +58,32 @@ public class PlaceRegistry public void invoke (PlaceManager plmgr); } - /** The location provider used by the place registry to provide location-related invocation - * services. */ - public LocationProvider locprov; - /** * Creates and initializes the place registry. This is called by the server during its * initialization phase. */ - @Inject public PlaceRegistry (ShutdownManager shutmgr, InvocationManager invmgr, - RootDObjectManager omgr) + @Inject public PlaceRegistry (ShutdownManager shutmgr) { shutmgr.registerShutdowner(this); - - // create and register our location provider - locprov = new LocationProvider(invmgr, omgr, this); - invmgr.registerDispatcher(new LocationDispatcher(locprov), CrowdCodes.CROWD_GROUP); - - // we'll need these later - _omgr = omgr; - _invmgr = invmgr; } /** - * By overriding this method, it is possible to customize the place registry to cause it to - * load the classes associated with a particular place via a custom class loader. That loader - * may enforce restricted privileges or obtain the classes from some special source. - * - * @return the class loader to use when instantiating the {@link PlaceManager} associated with - * the supplied {@link PlaceConfig}. This method must not return null. + * Provides the place registry with access to an injector that it can use to create {@link + * PlaceManager} instances with all dependencies resolved. This is called by the {@link + * CrowdServer} during the server initialization phase. */ - public ClassLoader getClassLoader (PlaceConfig config) + public void setInjector (Injector injector) { - return getClass().getClassLoader(); + _injector = injector; + } + + /** + * Returns the place manager associated with the specified place object id or null if no such + * place exists. + */ + public PlaceManager getPlaceManager (int placeOid) + { + return _pmgrs.get(placeOid); } /** @@ -142,15 +136,6 @@ public class PlaceRegistry return createPlace(config, null, hook); } - /** - * Returns the place manager associated with the specified place object id or null if no such - * place exists. - */ - public PlaceManager getPlaceManager (int placeOid) - { - return _pmgrs.get(placeOid); - } - /** * Returns an enumeration of all of the registered place objects. This should only be accessed * on the dobjmgr thread and shouldn't be kept around across event dispatches. @@ -204,12 +189,10 @@ public class PlaceRegistry throws InstantiationException, InvocationException { PlaceManager pmgr = null; - ClassLoader loader = getClassLoader(config); try { // create a place manager using the class supplied in the place config - pmgr = (PlaceManager)Class.forName( - config.getManagerClassName(), true, loader).newInstance(); + pmgr = createPlaceManager(config); // if we have delegates, add them if (delegates != null) { @@ -226,8 +209,7 @@ public class PlaceRegistry throw new InstantiationException("Error creating PlaceManager for " + config); } - // give the manager an opportunity to abort the whole process if it fails any permissions - // checks + // let the manager abort the whole process if it fails any permissions checks String errmsg = pmgr.checkPermissions(); if (errmsg != null) { // give the place manager a chance to clean up after its early initialization process @@ -256,6 +238,20 @@ public class PlaceRegistry return pmgr; } + /** + * Creates an instance of a {@link PlaceManager} using the information in the supplied place + * config. Derived classes may wish to specialize this process for certain places for example + * loading user supplied place management code from a special class loader that sandboxes their + * code. + */ + protected PlaceManager createPlaceManager (PlaceConfig config) + throws Exception + { + @SuppressWarnings("unchecked") Class clazz = + (Class) Class.forName(config.getManagerClassName()); + return _injector.getInstance(clazz); + } + /** * Called by the place manager when it has been shut down. */ @@ -273,10 +269,13 @@ public class PlaceRegistry } /** The invocation manager with which we operate. */ - protected InvocationManager _invmgr; + @Inject protected InvocationManager _invmgr; /** The distributed object manager with which we operate. */ - protected RootDObjectManager _omgr; + @Inject protected RootDObjectManager _omgr; + + /** We use this to inject dependencies into place managers that we create. */ + protected Injector _injector; /** A mapping from place object id to place manager. */ protected IntMap _pmgrs = IntMaps.newHashIntMap(); diff --git a/tests/src/java/com/threerings/bureau/server/RegistryTester.java b/tests/src/java/com/threerings/bureau/server/RegistryTester.java index 884a58918..55bb605ee 100644 --- a/tests/src/java/com/threerings/bureau/server/RegistryTester.java +++ b/tests/src/java/com/threerings/bureau/server/RegistryTester.java @@ -30,10 +30,11 @@ import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; -import com.threerings.bureau.data.AgentObject; - +import com.threerings.presents.dobj.RootDObjectManager; import com.threerings.presents.server.ShutdownManager; +import com.threerings.bureau.data.AgentObject; + import static com.threerings.bureau.Log.log; /** @@ -173,11 +174,11 @@ public class RegistryTester } // create or destroy some agents - TestServer.omgr.postRunnable(createOrDestroyAgents); + _omgr.postRunnable(createOrDestroyAgents); } // clean up - TestServer.omgr.postRunnable(new Runnable() { + _omgr.postRunnable(new Runnable() { public void run () { for (AgentObject obj : _agents) { TestServer.breg.destroyAgent(obj); @@ -217,6 +218,8 @@ public class RegistryTester return obj; } + @Inject protected RootDObjectManager _omgr; + protected TestServer _server; protected boolean _stop; protected Random _rng1;