From 46a23342b385eb23d129c5b7483a041c34d95b43 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Mon, 12 Feb 2007 03:40:14 +0000 Subject: [PATCH] More jockeying to make String[] streaming work and to make service group registration work. Keeerist Flash is annoying. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4562 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../com/threerings/io/ObjectOutputStream.as | 16 ++--- src/as/com/threerings/io/TypedArray.as | 12 ++++ .../threerings/io/streamers/ArrayStreamer.as | 9 +-- .../presents/client/BasicDirector.as | 3 + .../com/threerings/presents/client/Client.as | 60 +++++++++++-------- .../threerings/presents/net/AuthRequest.as | 5 +- 6 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/as/com/threerings/io/ObjectOutputStream.as b/src/as/com/threerings/io/ObjectOutputStream.as index ad4677a9f..fe7bac5eb 100644 --- a/src/as/com/threerings/io/ObjectOutputStream.as +++ b/src/as/com/threerings/io/ObjectOutputStream.as @@ -1,3 +1,6 @@ +// +// $Id$ + package com.threerings.io { import flash.utils.ByteArray; @@ -86,8 +89,7 @@ public class ObjectOutputStream } /** - * This is equivalent to marshalling a field for which there - * is a basic streamer. + * This is equivalent to marshalling a field for which there is a basic streamer. */ public function writeField (val :Object) :void //throws IOError @@ -100,10 +102,9 @@ public class ObjectOutputStream } /** - * Uses the default streamable mechanism to write the contents of the - * object currently being streamed. This can only be called from - * within a writeObject implementation in a {@link - * Streamable} object. + * Uses the default streamable mechanism to write the contents of the object currently being + * streamed. This can only be called from within a writeObject implementation in a + * {@link Streamable} object. */ public function defaultWriteObject () :void //throws IOError @@ -166,8 +167,7 @@ public class ObjectOutputStream _targ.writeUTF(value); } - // these two are defined in IDataOutput, but have no java equivalent so - // we skip them. + // these two are defined in IDataOutput, but have no java equivalent so we skip them. //public function writeUnsignedInt (value :int) :void //public function writeUTFBytes (value :int) :void diff --git a/src/as/com/threerings/io/TypedArray.as b/src/as/com/threerings/io/TypedArray.as index d1503f60e..6246615bd 100644 --- a/src/as/com/threerings/io/TypedArray.as +++ b/src/as/com/threerings/io/TypedArray.as @@ -50,6 +50,18 @@ public dynamic class TypedArray extends Array _jtype = jtype; } + /** + * Adds all of the elements of the supplied array to this typed array. The types of the + * elements of the target array must, of course, be of the type specified for this array + * otherwise badness will ensue. + */ + public function addAll (other :Array) :void + { + for (var ii :int = 0; ii < other.length; ii++) { + this[ii] = other[ii]; + } + } + public function getJavaType () :String { return _jtype; diff --git a/src/as/com/threerings/io/streamers/ArrayStreamer.as b/src/as/com/threerings/io/streamers/ArrayStreamer.as index fc072d909..3b170a0a1 100644 --- a/src/as/com/threerings/io/streamers/ArrayStreamer.as +++ b/src/as/com/threerings/io/streamers/ArrayStreamer.as @@ -30,6 +30,9 @@ public class ArrayStreamer extends Streamer baseClass = Translations.getFromServer(baseClass); _elementType = ClassUtil.getClassByName(baseClass); _isFinal = ClassUtil.isFinal(_elementType); + if (_elementType == String) { + _delegate = new StringStreamer(); + } } else if (secondChar === "I") { _elementType = int; @@ -76,8 +79,7 @@ public class ArrayStreamer extends Streamer return ta; } - override public function writeObject (obj :Object, out :ObjectOutputStream) - :void + override public function writeObject (obj :Object, out :ObjectOutputStream) :void { var arr :Array = (obj as Array); var ii :int; @@ -115,8 +117,7 @@ public class ArrayStreamer extends Streamer } } - override public function readObject (obj :Object, ins :ObjectInputStream) - :void + override public function readObject (obj :Object, ins :ObjectInputStream) :void { var arr :Array = (obj as Array); var ii :int; diff --git a/src/as/com/threerings/presents/client/BasicDirector.as b/src/as/com/threerings/presents/client/BasicDirector.as index 1accac256..6bc1aeb79 100644 --- a/src/as/com/threerings/presents/client/BasicDirector.as +++ b/src/as/com/threerings/presents/client/BasicDirector.as @@ -49,6 +49,9 @@ public class BasicDirector // if we're already logged on, fire off a call to fetch services if (client.isLoggedOn()) { + // this is a sanity check: it will fail if this post-logon initialized director claims + // to need service groups (it must make that known prior to logon) + registerServices(client); fetchServices(client); clientObjectUpdated(client); } diff --git a/src/as/com/threerings/presents/client/Client.as b/src/as/com/threerings/presents/client/Client.as index 7c957852e..9d542d1db 100644 --- a/src/as/com/threerings/presents/client/Client.as +++ b/src/as/com/threerings/presents/client/Client.as @@ -1,3 +1,6 @@ +// +// $Id$ + package com.threerings.presents.client { import flash.display.Stage; @@ -59,9 +62,8 @@ public class Client extends EventDispatcher } /** - * Unregisters the supplied observer. Upon return of this function, - * the observer will no longer receive notifications of state changes - * within the client. + * 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 { @@ -176,8 +178,11 @@ public class Client extends EventDispatcher */ public function addServiceGroup (group :String) :void { + if (isLoggedOn()) { + throw new Error("Services must be registered prior to logon()."); + } if (_bootGroups.indexOf(group) == -1) { - _bootGroups.concat(group); + _bootGroups.push(group); } } @@ -226,28 +231,35 @@ public class Client extends EventDispatcher return false; } + // let our observers know that we're logging on (this will give directors a chance to + // register invocation service groups) notifyObservers(ClientEvent.CLIENT_WILL_LOGON); + // we need to wait for the CLIENT_WILL_LOGON to have been dispatched before we actually + // tell the communicator to logon, so we run this through the callLater pipeline _comm = new Communicator(this); - _comm.logon(); + callLater(function () :void { + _comm.logon(); + }); + // it is safe, however, to start up our tick interval immediately if (_tickInterval == null) { _tickInterval = new Timer(5000); _tickInterval.addEventListener(TimerEvent.TIMER, tick); _tickInterval.start(); } + return true; } /** * Requests that the client log off of the server to which it is connected. * - * @param abortable if true, the client will call clientWillDisconnect - * on allthe client observers and abort the logoff process if any of them - * return false. If false, clientWillDisconnect will not be called. + * @param abortable if true, the client will call clientWillDisconnect on allthe client + * observers and abort the logoff process if any of them return false. If false, + * clientWillDisconnect will not be called. * - * @return true if the logoff succeeded, false if it failed due to a - * disagreeable observer. + * @return true if the logoff succeeded, false if it failed due to a disagreeable observer. */ public function logoff (abortable :Boolean) :Boolean { @@ -256,9 +268,8 @@ public class Client extends EventDispatcher return true; } - // if the request is abortable, let's run it past the observers. - // if any of them call preventDefault() then the logoff will be - // cancelled + // if the request is abortable, let's run it past the observers. if any of them call + // preventDefault() then the logoff will be cancelled if (abortable && !notifyObservers(ClientEvent.CLIENT_WILL_LOGOFF)) { return false; } @@ -285,8 +296,8 @@ public class Client extends EventDispatcher } /** - * Called every five seconds; ensures that we ping the server if we - * haven't communicated in a long while. + * Called every five seconds; ensures that we ping the server if we haven't communicated in a + * long while. */ protected function tick (event :TimerEvent) :void { @@ -301,8 +312,8 @@ public class Client extends EventDispatcher } /** - * Called by the {@link Communicator} if it is experiencing trouble logging - * on but is still trying fallback strategies. + * Called by the {@link Communicator} if it is experiencing trouble logging on but is still + * trying fallback strategies. */ internal function reportLogonTribulations (cause :LogonError) :void { @@ -310,8 +321,8 @@ public class Client extends EventDispatcher } /** - * Called by the invocation director when it successfully subscribes - * to the client object immediately following logon. + * Called by the invocation director when it successfully subscribes to the client object + * immediately following logon. */ public function gotClientObject (clobj :ClientObject) :void { @@ -320,8 +331,7 @@ public class Client extends EventDispatcher } /** - * Called by the invocation director if it fails to subscribe to the - * client object after logon. + * Called by the invocation director if it fails to subscribe to the client object after logon. */ public function getClientObjectFailed (cause :Error) :void { @@ -329,8 +339,7 @@ public class Client extends EventDispatcher } /** - * Called by the invocation director when it discovers that the client - * object has changed. + * Called by the invocation director when it discovers that the client object has changed. */ protected function clientObjectDidChange (clobj :ClientObject) :void { @@ -351,9 +360,8 @@ public class Client extends EventDispatcher // and let our invocation director know we're logged off _invdir.cleanup(); - // if this was due to a logon error, we can notify our listeners - // now that we're cleaned up: they may want to retry logon on - // another port, or something + // if this was due to a logon error, we can notify our listeners now that we're cleaned up: + // they may want to retry logon on another port, or something if (logonError != null) { notifyObservers(ClientEvent.CLIENT_FAILED_TO_LOGON, logonError); } else { diff --git a/src/as/com/threerings/presents/net/AuthRequest.as b/src/as/com/threerings/presents/net/AuthRequest.as index a9bbf08e3..7a744fb8c 100644 --- a/src/as/com/threerings/presents/net/AuthRequest.as +++ b/src/as/com/threerings/presents/net/AuthRequest.as @@ -1,3 +1,6 @@ +// +// $Id$ + package com.threerings.presents.net { import com.threerings.io.ObjectInputStream; @@ -13,7 +16,7 @@ public class AuthRequest extends UpstreamMessage _creds = creds; _version = version; _bootGroups = new TypedArray("[Ljava.lang.String;"); - _bootGroups.concat(bootGroups); + _bootGroups.addAll(bootGroups); // magic up a timezone in the format "GMT+XX:XX" // Of course, the sign returned from getTimezoneOffset() is wrong