I write two lines in the morning. I write two lines at night.

I write two lines in the afternoon and it makes me feel alright.
I write two lines in times of peace, I write two in times of war.
I write two lines before I write two lines, and then I write two more.

Bringing ActionScript world into line with the Javver.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4556 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2007-02-11 03:28:48 +00:00
parent b7e16c86f5
commit cb5fd7ff55
11 changed files with 151 additions and 54 deletions
@@ -45,6 +45,7 @@ import com.threerings.util.TimeUtil;
import com.threerings.crowd.client.LocationObserver; import com.threerings.crowd.client.LocationObserver;
import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.data.CrowdCodes;
import com.threerings.crowd.data.PlaceObject; import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext; import com.threerings.crowd.util.CrowdContext;
@@ -984,7 +985,13 @@ public class ChatDirector extends BasicDirector
return (typ == null) ? ChatCodes.PLACE_CHAT_TYPE : typ; return (typ == null) ? ChatCodes.PLACE_CHAT_TYPE : typ;
} }
// documentation inherited from interface // from BasicDirector
override protected function registerServices (client :Client) :void
{
client.addServiceGroup(CrowdCodes.CROWD_GROUP);
}
// from BasicDirector
override protected function fetchServices (client :Client) :void override protected function fetchServices (client :Client) :void
{ {
// get a handle on our chat service // get a handle on our chat service
@@ -36,6 +36,7 @@ import com.threerings.presents.dobj.Subscriber;
import com.threerings.presents.dobj.SubscriberAdapter; import com.threerings.presents.dobj.SubscriberAdapter;
import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.data.CrowdCodes;
import com.threerings.crowd.data.LocationCodes; import com.threerings.crowd.data.LocationCodes;
import com.threerings.crowd.data.PlaceConfig; import com.threerings.crowd.data.PlaceConfig;
import com.threerings.crowd.data.PlaceObject; import com.threerings.crowd.data.PlaceObject;
@@ -424,12 +425,17 @@ public class LocationDirector extends BasicDirector
_lservice = null; _lservice = null;
} }
// documentation inherited // from BasicDirector
override protected function registerServices (client :Client) :void
{
client.addServiceGroup(CrowdCodes.CROWD_GROUP);
}
// from BasicDirector
override protected function fetchServices (client :Client) :void override protected function fetchServices (client :Client) :void
{ {
// obtain our service handle // obtain our service handle
_lservice = _lservice = (client.requireService(LocationService) as LocationService);
(client.requireService(LocationService) as LocationService);
} }
protected function gotBodyObject (clobj :BodyObject) :void protected function gotBodyObject (clobj :BodyObject) :void
@@ -0,0 +1,34 @@
//
// $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.crowd.data {
import com.threerings.presents.data.InvocationCodes;
/**
* Defines codes and constants global to the Crowd services.
*/
public class CrowdCodes extends InvocationCodes
{
/** Defines our invocation services group. */
public static const CROWD_GROUP :String = "crowd";
}
}
@@ -54,6 +54,13 @@ public class BasicDirector
} }
} }
// documentation inherited from interface SessionObserver
public function clientWillLogon (event :ClientEvent) :void
{
var client :Client = event.getClient();
registerServices(client);
}
// documentation inherited from interface SessionObserver // documentation inherited from interface SessionObserver
public function clientDidLogon (event :ClientEvent) :void public function clientDidLogon (event :ClientEvent) :void
{ {
@@ -82,6 +89,15 @@ public class BasicDirector
{ {
} }
/**
* If a director makes use of bootstrap invocation services which are part of a bootstrap
* service group, it should register interest in that group here with a call to {@link
* Client#addServiceGroup}.
*/
protected function registerServices (client :Client) :void
{
}
/** /**
* Derived directors can override this method and obtain any services * Derived directors can override this method and obtain any services
* they'll need during their operation via calls to {@link * they'll need during their operation via calls to {@link
+49 -36
View File
@@ -11,6 +11,7 @@ import com.threerings.util.MethodQueue;
import com.threerings.util.ObserverList; import com.threerings.util.ObserverList;
import com.threerings.presents.data.ClientObject; import com.threerings.presents.data.ClientObject;
import com.threerings.presents.data.InvocationCodes;
import com.threerings.presents.dobj.DObjectManager; import com.threerings.presents.dobj.DObjectManager;
@@ -35,32 +36,25 @@ public class Client extends EventDispatcher
} }
/** /**
* Registers the supplied observer with this client. While registered * Registers the supplied observer with this client. While registered the observer will receive
* the observer will receive notifications of state changes within the * notifications of state changes within the client. The function will refuse to register an
* client. The function will refuse to register an already registered * already registered observer.
* observer.
* *
* @see ClientObserver * @see ClientObserver
* @see SessionObserver * @see SessionObserver
*/ */
public function addClientObserver (observer :SessionObserver) :void public function addClientObserver (observer :SessionObserver) :void
{ {
addEventListener(ClientEvent.CLIENT_DID_LOGON, addEventListener(ClientEvent.CLIENT_WILL_LOGON, observer.clientWillLogon);
observer.clientDidLogon); addEventListener(ClientEvent.CLIENT_DID_LOGON, observer.clientDidLogon);
addEventListener(ClientEvent.CLIENT_OBJECT_CHANGED, addEventListener(ClientEvent.CLIENT_OBJECT_CHANGED, observer.clientObjectDidChange);
observer.clientObjectDidChange); addEventListener(ClientEvent.CLIENT_DID_LOGOFF, observer.clientDidLogoff);
addEventListener(ClientEvent.CLIENT_DID_LOGOFF,
observer.clientDidLogoff);
if (observer is ClientObserver) { if (observer is ClientObserver) {
var cliObs :ClientObserver = (observer as ClientObserver); var cliObs :ClientObserver = (observer as ClientObserver);
addEventListener(ClientEvent.CLIENT_FAILED_TO_LOGON, addEventListener(ClientEvent.CLIENT_FAILED_TO_LOGON, cliObs.clientFailedToLogon);
cliObs.clientFailedToLogon); addEventListener(ClientEvent.CLIENT_CONNECTION_FAILED, cliObs.clientConnectionFailed);
addEventListener(ClientEvent.CLIENT_CONNECTION_FAILED, addEventListener(ClientEvent.CLIENT_WILL_LOGOFF, cliObs.clientWillLogoff);
cliObs.clientConnectionFailed); addEventListener(ClientEvent.CLIENT_DID_CLEAR, cliObs.clientDidClear);
addEventListener(ClientEvent.CLIENT_WILL_LOGOFF,
cliObs.clientWillLogoff);
addEventListener(ClientEvent.CLIENT_DID_CLEAR,
cliObs.clientDidClear);
} }
} }
@@ -71,22 +65,17 @@ public class Client extends EventDispatcher
*/ */
public function removeClientObserver (observer :SessionObserver) :void public function removeClientObserver (observer :SessionObserver) :void
{ {
removeEventListener(ClientEvent.CLIENT_DID_LOGON, removeEventListener(ClientEvent.CLIENT_WILL_LOGON, observer.clientWillLogon);
observer.clientDidLogon); removeEventListener(ClientEvent.CLIENT_DID_LOGON, observer.clientDidLogon);
removeEventListener(ClientEvent.CLIENT_OBJECT_CHANGED, removeEventListener(ClientEvent.CLIENT_OBJECT_CHANGED, observer.clientObjectDidChange);
observer.clientObjectDidChange); removeEventListener(ClientEvent.CLIENT_DID_LOGOFF, observer.clientDidLogoff);
removeEventListener(ClientEvent.CLIENT_DID_LOGOFF,
observer.clientDidLogoff);
if (observer is ClientObserver) { if (observer is ClientObserver) {
var cliObs :ClientObserver = (observer as ClientObserver); var cliObs :ClientObserver = (observer as ClientObserver);
removeEventListener(ClientEvent.CLIENT_FAILED_TO_LOGON, removeEventListener(ClientEvent.CLIENT_FAILED_TO_LOGON, cliObs.clientFailedToLogon);
cliObs.clientFailedToLogon); removeEventListener(
removeEventListener(ClientEvent.CLIENT_CONNECTION_FAILED, ClientEvent.CLIENT_CONNECTION_FAILED, cliObs.clientConnectionFailed);
cliObs.clientConnectionFailed); removeEventListener(ClientEvent.CLIENT_WILL_LOGOFF, cliObs.clientWillLogoff);
removeEventListener(ClientEvent.CLIENT_WILL_LOGOFF, removeEventListener(ClientEvent.CLIENT_DID_CLEAR, cliObs.clientDidClear);
cliObs.clientWillLogoff);
removeEventListener(ClientEvent.CLIENT_DID_CLEAR,
cliObs.clientDidClear);
} }
} }
@@ -172,6 +161,26 @@ public class Client extends EventDispatcher
return _invdir; return _invdir;
} }
/**
* Returns the set of bootstrap service groups needed by this client.
*/
public function getBootGroups () :Array
{
return _bootGroups;
}
/**
* Marks this client as interested in the specified bootstrap services group. Any services
* registered as bootstrap services with the supplied group name will be included in this
* clients bootstrap services set. This must be called before {@link #logon}.
*/
public function addServiceGroup (group :String) :void
{
if (_bootGroups.indexOf(group) == -1) {
_bootGroups.concat(group);
}
}
public function getService (clazz :Class) :InvocationService public function getService (clazz :Class) :InvocationService
{ {
if (_bstrap != null) { if (_bstrap != null) {
@@ -205,8 +214,8 @@ public class Client extends EventDispatcher
} }
/** /**
* Requests that this client connect and logon to the server with * Requests that this client connect and logon to the server with which it was previously
* which it was previously configured. * configured.
* *
* @return false if we're already logged on. * @return false if we're already logged on.
*/ */
@@ -217,6 +226,8 @@ public class Client extends EventDispatcher
return false; return false;
} }
notifyObservers(ClientEvent.CLIENT_WILL_LOGON);
_comm = new Communicator(this); _comm = new Communicator(this);
_comm.logon(); _comm.logon();
@@ -229,8 +240,7 @@ public class Client extends EventDispatcher
} }
/** /**
* Requests that the client log off of the server to which it is * Requests that the client log off of the server to which it is connected.
* connected.
* *
* @param abortable if true, the client will call clientWillDisconnect * @param abortable if true, the client will call clientWillDisconnect
* on allthe client observers and abort the logoff process if any of them * on allthe client observers and abort the logoff process if any of them
@@ -403,6 +413,9 @@ public class Client extends EventDispatcher
// protected var _observers :ObserverList = // protected var _observers :ObserverList =
// new ObserverList(ObserverList.SAFE_IN_ORDER_NOTIFY); // new ObserverList(ObserverList.SAFE_IN_ORDER_NOTIFY);
/** The set of bootstrap service groups this client cares about. */
protected var _bootGroups :Array = new Array(InvocationCodes.GLOBAL_GROUP);
/** General startup information provided by the server. */ /** General startup information provided by the server. */
protected var _bstrap :BootstrapData; protected var _bstrap :BootstrapData;
@@ -4,6 +4,7 @@ public class ClientAdapter
implements ClientObserver implements ClientObserver
{ {
public function ClientAdapter ( public function ClientAdapter (
clientWillLogon :Function = null,
clientDidLogon :Function = null, clientDidLogon :Function = null,
clientObjectDidChange :Function = null, clientObjectDidChange :Function = null,
clientDidLogoff :Function = null, clientDidLogoff :Function = null,
@@ -12,6 +13,7 @@ public class ClientAdapter
clientWillLogoff :Function = null, clientWillLogoff :Function = null,
clientDidClear :Function = null) clientDidClear :Function = null)
{ {
_clientWillLogon = clientWillLogon;
_clientDidLogon = clientDidLogon; _clientDidLogon = clientDidLogon;
_clientObjectDidChange = clientObjectDidChange; _clientObjectDidChange = clientObjectDidChange;
_clientDidLogoff = clientDidLogoff; _clientDidLogoff = clientDidLogoff;
@@ -21,6 +23,14 @@ public class ClientAdapter
_clientDidClear = clientDidClear; _clientDidClear = clientDidClear;
} }
// from ClientObserver
public function clientWillLogon (event :ClientEvent) :void
{
if (_clientWillLogon != null) {
_clientWillLogon(event);
}
}
// from ClientObserver // from ClientObserver
public function clientDidLogon (event :ClientEvent) :void public function clientDidLogon (event :ClientEvent) :void
{ {
@@ -77,6 +87,7 @@ public class ClientAdapter
} }
} }
protected var _clientWillLogon :Function;
protected var _clientDidLogon :Function; protected var _clientDidLogon :Function;
protected var _clientObjectDidChange :Function; protected var _clientObjectDidChange :Function;
protected var _clientDidLogoff :Function; protected var _clientDidLogoff :Function;
@@ -4,6 +4,7 @@ import flash.events.Event;
public class ClientEvent extends Event public class ClientEvent extends Event
{ {
public static const CLIENT_WILL_LOGON :String = "clientWillLogon";
public static const CLIENT_DID_LOGON :String = "clientDidLogon"; public static const CLIENT_DID_LOGON :String = "clientDidLogon";
public static const CLIENT_FAILED_TO_LOGON :String = "clientFailedLogon"; public static const CLIENT_FAILED_TO_LOGON :String = "clientFailedLogon";
public static const CLIENT_OBJECT_CHANGED :String = "clobjChanged"; public static const CLIENT_OBJECT_CHANGED :String = "clobjChanged";
@@ -244,8 +244,8 @@ public class Communicator
{ {
logonToPort(true); logonToPort(true);
// well that's great! let's logon // well that's great! let's logon
var req :AuthRequest = new AuthRequest(_client.getCredentials(), var req :AuthRequest = new AuthRequest(
_client.getVersion()); _client.getCredentials(), _client.getVersion(), _client.getBootGroups());
sendMessage(req); sendMessage(req);
} }
@@ -30,6 +30,11 @@ package com.threerings.presents.client {
*/ */
public interface SessionObserver public interface SessionObserver
{ {
/**
* Called immediately before a logon is attempted.
*/
function clientWillLogon (event :ClientEvent) :void;
/** /**
* Called after the client successfully connected to and authenticated * Called after the client successfully connected to and authenticated
* with the server. The entire object system is up and running by the * with the server. The entire object system is up and running by the
@@ -22,23 +22,24 @@
package com.threerings.presents.data { package com.threerings.presents.data {
/** /**
* The invocation codes interface provides codes that are commonly used by * The invocation codes interface provides codes that are commonly used by invocation service
* invocation service implementations. It is implemented as an interface * implementations. It is implemented as an interface so that were an invocation service to desire
* so that were an invocation service to desire to build on two or more * to build on two or more other services, it can provide a codes interface that inherits from all
* other services, it can provide a codes interface that inherits from all
* of the services that it extends. * of the services that it extends.
*/ */
public class InvocationCodes public class InvocationCodes
{ {
/** An error code returned to clients when a service cannot be /** Defines a global invocation services group that can be used by clients and services that do
* performed because of some internal server error that we couldn't * not care to make a distinction between groups of invocation services. */
* explain in any meaningful way (things like null pointer public static const GLOBAL_GROUP :String = "presents";
* exceptions). */
/** An error code returned to clients when a service cannot be performed because of some
* internal server error that we couldn't explain in any meaningful way (things like null
* pointer exceptions). */
public static const INTERNAL_ERROR :String = "m.internal_error"; public static const INTERNAL_ERROR :String = "m.internal_error";
/** An error code returned to clients when a service cannot be /** An error code returned to clients when a service cannot be performed because the requesting
* performed because the requesting client does not have the proper * client does not have the proper access. */
* access. */
public static const ACCESS_DENIED :String = "m.access_denied"; public static const ACCESS_DENIED :String = "m.access_denied";
} }
} }
@@ -7,10 +7,11 @@ import com.threerings.util.StringUtil;
public class AuthRequest extends UpstreamMessage public class AuthRequest extends UpstreamMessage
{ {
public function AuthRequest (creds :Credentials, version :String) public function AuthRequest (creds :Credentials, version :String, bootGroups :Array)
{ {
_creds = creds; _creds = creds;
_version = version; _version = version;
_bootGroups = bootGroups;
// magic up a timezone in the format "GMT+XX:XX" // magic up a timezone in the format "GMT+XX:XX"
// Of course, the sign returned from getTimezoneOffset() is wrong // Of course, the sign returned from getTimezoneOffset() is wrong
@@ -30,10 +31,12 @@ public class AuthRequest extends UpstreamMessage
out.writeObject(_creds); out.writeObject(_creds);
out.writeField(_version); out.writeField(_version);
out.writeField(_zone); out.writeField(_zone);
out.writeField(_bootGroups);
} }
protected var _creds :Credentials; protected var _creds :Credentials;
protected var _version :String; protected var _version :String;
protected var _zone :String; protected var _zone :String;
protected var _bootGroups :Array;
} }
} }