From 3e5060c7c59ee89d7dc22ed23af8173ea28fdf62 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Mon, 23 Jul 2001 22:59:43 +0000 Subject: [PATCH] More location management progress. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@116 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- docs/presents/notes.txt | 2 + .../crowd/client/LocationDirector.java | 123 +++++++++++++++++- .../crowd/client/LocationObserver.java | 40 +++++- 3 files changed, 160 insertions(+), 5 deletions(-) diff --git a/docs/presents/notes.txt b/docs/presents/notes.txt index aaec39a24..53147fcb2 100644 --- a/docs/presents/notes.txt +++ b/docs/presents/notes.txt @@ -8,6 +8,8 @@ Implement object destroyed; finish wiring up oid list tracking. Ensure at time of OBJECT_ADDED that the object being added exists and has not been destroyed. +clientWillLogff becomes clientMayLogoff? + * Server-side event concentrator The client objects will not subscribe directly, but will subscribe through the concentrator so that, at least, it can create a single diff --git a/src/java/com/threerings/crowd/client/LocationDirector.java b/src/java/com/threerings/crowd/client/LocationDirector.java index c1cd21c9e..91076f83e 100644 --- a/src/java/com/threerings/crowd/client/LocationDirector.java +++ b/src/java/com/threerings/crowd/client/LocationDirector.java @@ -1,13 +1,17 @@ // -// $Id: LocationDirector.java,v 1.3 2001/07/23 21:14:27 mdb Exp $ +// $Id: LocationDirector.java,v 1.4 2001/07/23 22:59:43 mdb Exp $ package com.threerings.cocktail.party.client; +import java.util.ArrayList; +import java.util.List; + import com.threerings.cocktail.cher.client.*; import com.threerings.cocktail.cher.dobj.*; import com.threerings.cocktail.party.Log; import com.threerings.cocktail.party.data.BodyObject; +import com.threerings.cocktail.party.data.PlaceObject; import com.threerings.cocktail.party.util.PartyContext; /** @@ -18,7 +22,7 @@ import com.threerings.cocktail.party.util.PartyContext; * before actually issuing the request. */ public class LocationManager - implements ClientObserver + implements ClientObserver, Subscriber { public LocationManager (PartyContext ctx) { @@ -36,6 +40,33 @@ public class LocationManager */ public void moveTo (int placeId) { + // first check to see if our observers are happy with this move + // request + for (int i = 0; i < _observers.size(); i++) { + LocationObserver obs = (LocationObserver)_observers.get(i); + if (!obs.locationMayChange(placeId)) { + Log.info("Location change vetoed by observer " + + "[pid=" + placeId + ", obs=" + obs + "]."); + return; + } + } + + // complain if we're over-writing a pending request + if (_pendingPlaceId != -1) { + Log.warning("We appear to have a moveTo request outstanding " + + "[ppid=" + _pendingPlaceId + + ", npid=" + placeId + "]."); + // but we're going to fall through and do it anyway because + // refusing to switch rooms at this point will inevitably + // result in some strange bug causing a move request to be + // dropped by the server and the client that did it to be + // totally hosed because they can no longer move to new + // locations because they still have an outstanding request + } + + // make a note of our pending place id + _pendingPlaceId = placeId; + // issue a moveTo request LocationService.moveTo(_ctx.getClient(), placeId, this); } @@ -98,7 +129,21 @@ public class LocationManager */ public void handleMoveSucceeded () { - Log.info("Move succeeded."); + DObjectManager omgr = _ctx.getDObjectManager(); + + // unsubscribe from our old place object + if (_place != null) { + omgr.unsubscribeFromObject(_place.getOid(), this); + _place = null; + } + + // make a note that we're now mostly in the new location + _previousPlaceId = _placeId; + _placeId = _pendingPlaceId; + _pendingPlaceId = -1; + + // subscribe to our new place object to complete the move + omgr.subscribeToObject(_placeId, this); } /** @@ -106,8 +151,78 @@ public class LocationManager */ public void handleMoveFailed (String reason) { - Log.info("Move failed [reason=" + reason + "]."); + // clear out our pending request oid + int placeId = _pendingPlaceId; + _pendingPlaceId = -1; + + // let our observers know that something has gone horribly awry + notifyFailure(placeId, reason); } + public void objectAvailable (DObject object) + { + // yay, we have our new place object + _place = (PlaceObject)object; + + // let our observers know that all is well on the western front + for (int i = 0; i < _observers.size(); i++) { + LocationObserver obs = (LocationObserver)_observers.get(i); + obs.locationDidChange(_place); + } + } + + public void requestFailed (int oid, ObjectAccessException cause) + { + // aiya! we were unable to fetch our new place object; something + // is badly wrong + Log.warning("Aiya! Unable to fetch place object for new location " + + "[plid=" + oid + ", reason=" + cause + "]."); + + // clear out our half initialized place info + int placeId = _placeId; + _placeId = -1; + + // let the kids know shit be fucked + notifyFailure(placeId, "m.unable_to_fetch_place_object"); + + // if we were previously somewhere, try going back there + if (_previousPlaceId != -1) { + moveTo(_previousPlaceId); + } + } + + public boolean handleEvent (DEvent event, DObject target) + { + // nothing to do here, but remain subscribed + return true; + } + + protected void notifyFailure (int placeId, String reason) + { + for (int i = 0; i < _observers.size(); i++) { + LocationObserver obs = (LocationObserver)_observers.get(i); + obs.locationChangeFailed(placeId, reason); + } + } + + /** The context through which we access needed services. */ protected PartyContext _ctx; + + /** Our location observer list. */ + protected List _observers = new ArrayList(); + + /** The oid of the place we currently occupy. */ + protected int _placeId = -1; + + /** The place object that we currently occupy. */ + protected PlaceObject _place; + + /** + * The oid of the place for which we have an outstanding moveTo + * request, or -1 if we have no outstanding request. + */ + protected int _pendingPlaceId = -1; + + /** The oid of the place we previously occupied. */ + protected int _previousPlaceId = -1; } diff --git a/src/java/com/threerings/crowd/client/LocationObserver.java b/src/java/com/threerings/crowd/client/LocationObserver.java index 419bd24f4..435f7cb64 100644 --- a/src/java/com/threerings/crowd/client/LocationObserver.java +++ b/src/java/com/threerings/crowd/client/LocationObserver.java @@ -1,8 +1,46 @@ // -// $Id: LocationObserver.java,v 1.1 2001/07/20 20:07:37 mdb Exp $ +// $Id: LocationObserver.java,v 1.2 2001/07/23 22:59:43 mdb Exp $ package com.threerings.cocktail.party.client; +import com.threerings.cocktail.party.data.PlaceObject; + +/** + * The location observer interface makes it possible for entities to be + * notified when the client moves to a new location. It also provides a + * means for an entity to participate in the ratification process of a new + * location. Observers may opt to reject a request to change to a new + * location, probably because something is going on in the previous + * location that should not be abandoned. + * + *

Note that these location callbacks occur on the main thread and + * should execute quickly and not block under any circumstance. + */ public interface LocationObserver { + /** + * Called when someone has requested that we switch to a new location. + * An observer may choose to veto the location change request for some + * reason or other. + */ + public boolean locationMayChange (int placeId); + + /** + * Called when we have switched to a new location. + * + * @param place the place object that represents the new location or + * null if we have switched to no location. + */ + public void locationDidChange (PlaceObject place); + + /** + * This is called on all location observers when a location change + * request is rejected by the server or fails for some other reason. + * + * @param placeId the place id to which we attempted to relocate, but + * failed. + * @param reason the reason code that explains why the location change + * request was rejected or otherwise failed. + */ + public void locationChangeFailed (int placeId, String reason); }