More progress.

Created adapters for invocation services so that I can do inner-class like
things by passing references to private functions out to an external entity.
I will see if it's possible to merge my adapter with the marshallers
because it's still to have multiple wrappy classes.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3944 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2006-03-14 03:22:38 +00:00
parent 9195817853
commit 7c842a7e11
15 changed files with 1303 additions and 168 deletions
@@ -0,0 +1,99 @@
//
// $Id: BasicDirector.java 3393 2005-03-10 02:06:43Z andrzej $
//
// 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.presents.client {
import com.threerings.presents.util.PresentsContext;
/**
* Handles functionality common to nearly all client directors. They
* generally need to be session observers so that they can set themselves
* up when the client logs on (by overriding {@link #clientDidLogon}) and
* clean up after themselves when the client logs off (by overriding
* {@link #clientDidLogoff}).
*/
public class BasicDirector
implements SessionObserver
{
/**
* Derived directors will need to provide the basic director with a
* context that it can use to register itself with the necessary
* entities.
*/
protected function BasicDirector (ctx :PresentsContext)
{
// save context
_ctx = ctx;
// listen for session start and end
var client :Client = ctx.getClient();
client.addClientObserver(this);
// if we're already logged on, fire off a call to fetch services
if (client.isLoggedOn()) {
fetchServices(client);
clientObjectUpdated(client);
}
}
// documentation inherited from interface SessionObserver
public function clientDidLogon (event :ClientEvent) :void
{
var client :Client = event.getClient();
fetchServices(client);
clientObjectUpdated(client);
}
// documentation inherited from interface SessionObserver
public function clientObjectDidChange (event :ClientEvent) :void
{
clientObjectUpdated(event.getClient());
}
// documentation inherited from interface SessionObserver
public function clientDidLogoff (event :ClientEvent) :void
{
}
/**
* Called in three circumstances: when a director is created and we've
* already logged on; when we first log on and when the client object
* changes after we've already logged on.
*/
protected function clientObjectUpdated (client :Client) :void
{
}
/**
* Derived directors can override this method and obtain any services
* they'll need during their operation via calls to {@link
* Client#getService}. If the director is available, it will automatically
* be called when the client logs on or when the director is constructed
* if it is constructed after the client is already logged on.
*/
protected function fetchServices (client :Client) :void
{
}
/** The application context. */
protected var _ctx :PresentsContext;
}
}
@@ -26,6 +26,58 @@ public class Client extends EventDispatcher
_creds = creds;
}
/**
* Registers the supplied observer with this client. While registered
* the observer will receive notifications of state changes within the
* client. The function will refuse to register an already registered
* observer.
*
* @see ClientObserver
* @see SessionObserver
*/
public function addClientObserver (observer :SessionObserver) :void
{
addEventListener(ClientEvent.CLIENT_DID_LOGON,
observer.clientDidLogon);
addEventListener(ClientEvent.CLIENT_OBJECT_CHANGED,
observer.clientObjectDidChange);
addEventListener(ClientEvent.CLIENT_DID_LOGOFF,
observer.clientDidLogoff);
if (observer is ClientObserver) {
var cliObs :ClientObserver = (observer as ClientObserver);
addEventListener(ClientEvent.CLIENT_FAILED_TO_LOGON,
cliObs.clientFailedToLogon);
addEventListener(ClientEvent.CLIENT_CONNECTION_FAILED,
cliObs.clientConnectionFailed);
addEventListener(ClientEvent.CLIENT_WILL_LOGOFF,
cliObs.clientWillLogoff);
}
}
/**
* Unregisters the supplied observer. Upon return of this function,
* the observer will no longer receive notifications of state changes
* within the client.
*/
public function removeClientObserver (observer :SessionObserver) :void
{
removeEventListener(ClientEvent.CLIENT_DID_LOGON,
observer.clientDidLogon);
removeEventListener(ClientEvent.CLIENT_OBJECT_CHANGED,
observer.clientObjectDidChange);
removeEventListener(ClientEvent.CLIENT_DID_LOGOFF,
observer.clientDidLogoff);
if (observer is ClientObserver) {
var cliObs :ClientObserver = (observer as ClientObserver);
removeEventListener(ClientEvent.CLIENT_FAILED_TO_LOGON,
cliObs.clientFailedToLogon);
removeEventListener(ClientEvent.CLIENT_CONNECTION_FAILED,
cliObs.clientConnectionFailed);
removeEventListener(ClientEvent.CLIENT_WILL_LOGOFF,
cliObs.clientWillLogoff);
}
}
public function setServer (hostname :String, port :int) :void
{
_hostname = hostname;
@@ -0,0 +1,72 @@
//
// $Id: ClientObserver.java 3099 2004-08-27 02:21:06Z 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.presents.client {
/**
* A client observer is a more detailed version of the {@link
* SessionObserver} for entities that are interested in more detail about
* the logon/logoff process.
*
* <p> In the normal course of affairs, <code>clientDidLogon</code> will
* be called after the client successfully logs on to the server and
* <code>clientDidLogoff</code> will be called after the client logs off
* of the server. If logon fails for any reson,
* <code>clientFailedToLogon</code> will be called to explain the failure.
*
* <p> <code>clientWillLogoff</code> will only be called when an abortable
* logoff is requested (like when the user clicks on a logoff button of
* some sort). It will not be called during non-abortable logoff requests
* (like when the browser calls stop on the applet and is about to yank
* the rug out from under us). If an observer aborts the logoff request,
* it should notify the user in some way why the request was aborted
* (<em>but it shouldn't do so on the thread that calls
* <code>clientWillLogoff</code></em>).
*
* <p> If the client connection fails unexpectedly,
* <code>clientConnectionFailed</code> will be called to let the
* observers know that we lost our connection to the
* server. <code>clientDidLogoff</code> will be called immediately
* afterwards as a normal logoff procedure is effected.
*/
public interface ClientObserver extends SessionObserver
{
/**
* Called if anything fails during the logon attempt. This could be a
* network failure, authentication failure or otherwise. The exception
* provided will indicate the cause of the failure.
*/
function clientFailedToLogon (event :ClientEvent) :void;
/**
* Called when the connection to the server went away for some
* unexpected reason. This will be followed by a call to
* <code>clientDidLogoff</code>.
*/
function clientConnectionFailed (event :ClientEvent) :void;
/**
* Called when an abortable logoff request is made. If the observer
* calls event.preventDefault() then it will abort the logoff request.
*/
function clientWillLogoff (event :ClientEvent) :void;
}
}
@@ -0,0 +1,28 @@
package com.threerings.presents.client {
public class InvocationAdapter
implements InvocationListener
{
/**
* Construct an InvocationAdapter that will call the specified
* function on error.
*/
public function InvocationAdapter (failedFunc :Function, args :Array = null)
{
_failedFunc = failedFunc;
_args = args;
}
// documentation inherited from interface InvocationListener
public function requestFailed (cause :String) :void
{
_failedFunc(cause, _args);
}
/** The Function to call when we've recevied our failure response. */
protected var _failedFunc :Function;
/** Any other extra information to pass along to the function. */
protected var _args :Array;
}
}
@@ -0,0 +1,54 @@
//
// $Id: SessionObserver.java 3099 2004-08-27 02:21:06Z 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.presents.client {
/**
* A session observer is registered with the client instance to be
* notified when the client establishes and ends their session with the
* server.
*
* @see ClientObserver
*/
public interface SessionObserver
{
/**
* Called after the client successfully connected to and authenticated
* with the server. The entire object system is up and running by the
* time this method is called.
*/
function clientDidLogon (event :ClientEvent) :void;
/**
* For systems that allow switching screen names after logon, this
* method is called whenever a screen name change takes place to
* report that the client object has been replaced to potential
* client-side subscribers.
*/
function clientObjectDidChange (event :ClientEvent) :void;
/**
* Called after the client has been logged off of the server and has
* disconnected.
*/
function clientDidLogoff (event :ClientEvent) :void;
}
}
@@ -2,6 +2,8 @@ package com.threerings.presents.client {
import flash.util.describeType;
import mx.collections.ArrayCollection;
import com.threerings.util.Name;
import com.threerings.presents.Log;
import com.threerings.presents.data.TimeBaseMarshaller;
@@ -41,6 +43,26 @@ public class TestClient extends Client
Log.debug("arr[0]: " + arr[0]);
Log.debug("arr[1]: " + arr[1]);
Log.debug("arr[2]: " + arr[2]);
//testFunc(2);
var bob :Person = new Person("Bob");
var jim :Person = new Person("Jim");
var bob2 :Person = new Person("Bob");
bob.callPrintName(jim.printName);
Log.debug("bob == jim: " + (bob == jim));
Log.debug("bob === jim: " + (bob === jim));
Log.debug("bob == bob2: " + (bob == bob2));
Log.debug("bob === bob2: " + (bob === bob2));
Log.debug("bob == bob: " + (bob == bob));
Log.debug("bob === bob: " + (bob === bob));
var list :ArrayCollection = new ArrayCollection();
list.addItem(bob);
Log.debug("jim's indeX: " + list.getItemIndex(jim));
Log.debug("bob2's indeX: " + list.getItemIndex(bob2));
/*
var a :Object = new OldClass();
@@ -94,12 +116,45 @@ public class TestClient extends Client
{
var i :int = TimeBaseMarshaller.GET_TIME_OID;
}
public function testFunc (one :int, two :int = 0) :void
{
Log.debug("this: " + ", args: " + arguments.length +
": " + arguments);
}
prototype var _foo :String;
}
}
import com.threerings.presents.Log;
import com.threerings.presents.client.TestClient;
class Person
{
public function Person (name :String)
{
_name = name;
}
public function printName () :void
{
Log.debug("printName called on " + _name + "! (this=" + this + ")");
}
public function callPrintName (funcy :Function) :void
{
funcy();
}
public function toString () :String
{
return "Person[" + _name + "]";
}
protected var _name :String;
}
dynamic class OldClass
{
public function OldClass ()
@@ -0,0 +1,55 @@
//
// $Id: PresentsContext.java 3099 2004-08-27 02:21:06Z 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.presents.util {
//import com.samskivert.util.Config;
import com.threerings.presents.client.Client;
import com.threerings.presents.dobj.DObjectManager;
/**
* Provides access to standard services needed by code that is part of or
* uses the Presents package.
*/
public interface PresentsContext
{
// /**
// * Provides a configuration object from which various services can
// * obtain configuration values and via the properties file that forms
// * the basis of the configuration object, those services can be
// * customized.
// */
// public Config getConfig ();
/**
* Returns a reference to the client. This reference should be valid
* for the life of the application.
*/
function getClient () :Client;
/**
* Returns a reference to the distributed object manager. This
* reference is only valid for the duration of a session.
*/
function getDObjectManager () :DObjectManager;
}
}