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
This commit is contained in:
Michael Bayne
2007-02-12 03:40:14 +00:00
parent 40538c81ad
commit 46a23342b3
6 changed files with 66 additions and 39 deletions
@@ -1,3 +1,6 @@
//
// $Id$
package com.threerings.io { package com.threerings.io {
import flash.utils.ByteArray; import flash.utils.ByteArray;
@@ -86,8 +89,7 @@ public class ObjectOutputStream
} }
/** /**
* This is equivalent to marshalling a field for which there * This is equivalent to marshalling a field for which there is a basic streamer.
* is a basic streamer.
*/ */
public function writeField (val :Object) :void public function writeField (val :Object) :void
//throws IOError //throws IOError
@@ -100,10 +102,9 @@ public class ObjectOutputStream
} }
/** /**
* Uses the default streamable mechanism to write the contents of the * Uses the default streamable mechanism to write the contents of the object currently being
* object currently being streamed. This can only be called from * streamed. This can only be called from within a <code>writeObject</code> implementation in a
* within a <code>writeObject</code> implementation in a {@link * {@link Streamable} object.
* Streamable} object.
*/ */
public function defaultWriteObject () :void public function defaultWriteObject () :void
//throws IOError //throws IOError
@@ -166,8 +167,7 @@ public class ObjectOutputStream
_targ.writeUTF(value); _targ.writeUTF(value);
} }
// these two are defined in IDataOutput, but have no java equivalent so // these two are defined in IDataOutput, but have no java equivalent so we skip them.
// we skip them.
//public function writeUnsignedInt (value :int) :void //public function writeUnsignedInt (value :int) :void
//public function writeUTFBytes (value :int) :void //public function writeUTFBytes (value :int) :void
+12
View File
@@ -50,6 +50,18 @@ public dynamic class TypedArray extends Array
_jtype = jtype; _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 public function getJavaType () :String
{ {
return _jtype; return _jtype;
@@ -30,6 +30,9 @@ public class ArrayStreamer extends Streamer
baseClass = Translations.getFromServer(baseClass); baseClass = Translations.getFromServer(baseClass);
_elementType = ClassUtil.getClassByName(baseClass); _elementType = ClassUtil.getClassByName(baseClass);
_isFinal = ClassUtil.isFinal(_elementType); _isFinal = ClassUtil.isFinal(_elementType);
if (_elementType == String) {
_delegate = new StringStreamer();
}
} else if (secondChar === "I") { } else if (secondChar === "I") {
_elementType = int; _elementType = int;
@@ -76,8 +79,7 @@ public class ArrayStreamer extends Streamer
return ta; return ta;
} }
override public function writeObject (obj :Object, out :ObjectOutputStream) override public function writeObject (obj :Object, out :ObjectOutputStream) :void
:void
{ {
var arr :Array = (obj as Array); var arr :Array = (obj as Array);
var ii :int; var ii :int;
@@ -115,8 +117,7 @@ public class ArrayStreamer extends Streamer
} }
} }
override public function readObject (obj :Object, ins :ObjectInputStream) override public function readObject (obj :Object, ins :ObjectInputStream) :void
:void
{ {
var arr :Array = (obj as Array); var arr :Array = (obj as Array);
var ii :int; var ii :int;
@@ -49,6 +49,9 @@ public class BasicDirector
// if we're already logged on, fire off a call to fetch services // if we're already logged on, fire off a call to fetch services
if (client.isLoggedOn()) { 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); fetchServices(client);
clientObjectUpdated(client); clientObjectUpdated(client);
} }
+34 -26
View File
@@ -1,3 +1,6 @@
//
// $Id$
package com.threerings.presents.client { package com.threerings.presents.client {
import flash.display.Stage; import flash.display.Stage;
@@ -59,9 +62,8 @@ public class Client extends EventDispatcher
} }
/** /**
* Unregisters the supplied observer. Upon return of this function, * Unregisters the supplied observer. Upon return of this function, the observer will no longer
* the observer will no longer receive notifications of state changes * receive notifications of state changes within the client.
* within the client.
*/ */
public function removeClientObserver (observer :SessionObserver) :void public function removeClientObserver (observer :SessionObserver) :void
{ {
@@ -176,8 +178,11 @@ public class Client extends EventDispatcher
*/ */
public function addServiceGroup (group :String) :void public function addServiceGroup (group :String) :void
{ {
if (isLoggedOn()) {
throw new Error("Services must be registered prior to logon().");
}
if (_bootGroups.indexOf(group) == -1) { if (_bootGroups.indexOf(group) == -1) {
_bootGroups.concat(group); _bootGroups.push(group);
} }
} }
@@ -226,28 +231,35 @@ public class Client extends EventDispatcher
return false; 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); 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 = new Communicator(this);
_comm.logon(); callLater(function () :void {
_comm.logon();
});
// it is safe, however, to start up our tick interval immediately
if (_tickInterval == null) { if (_tickInterval == null) {
_tickInterval = new Timer(5000); _tickInterval = new Timer(5000);
_tickInterval.addEventListener(TimerEvent.TIMER, tick); _tickInterval.addEventListener(TimerEvent.TIMER, tick);
_tickInterval.start(); _tickInterval.start();
} }
return true; return true;
} }
/** /**
* Requests that the client log off of the server to which it is connected. * Requests that the client log off of the server to which it is connected.
* *
* @param abortable if true, the client will call clientWillDisconnect * @param abortable if true, the client will call clientWillDisconnect on allthe client
* on allthe client observers and abort the logoff process if any of them * observers and abort the logoff process if any of them return false. If false,
* return false. If false, clientWillDisconnect will not be called. * clientWillDisconnect will not be called.
* *
* @return true if the logoff succeeded, false if it failed due to a * @return true if the logoff succeeded, false if it failed due to a disagreeable observer.
* disagreeable observer.
*/ */
public function logoff (abortable :Boolean) :Boolean public function logoff (abortable :Boolean) :Boolean
{ {
@@ -256,9 +268,8 @@ public class Client extends EventDispatcher
return true; return true;
} }
// if the request is abortable, let's run it past the observers. // if the request is abortable, let's run it past the observers. if any of them call
// if any of them call preventDefault() then the logoff will be // preventDefault() then the logoff will be cancelled
// cancelled
if (abortable && !notifyObservers(ClientEvent.CLIENT_WILL_LOGOFF)) { if (abortable && !notifyObservers(ClientEvent.CLIENT_WILL_LOGOFF)) {
return false; return false;
} }
@@ -285,8 +296,8 @@ public class Client extends EventDispatcher
} }
/** /**
* Called every five seconds; ensures that we ping the server if we * Called every five seconds; ensures that we ping the server if we haven't communicated in a
* haven't communicated in a long while. * long while.
*/ */
protected function tick (event :TimerEvent) :void 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 * Called by the {@link Communicator} if it is experiencing trouble logging on but is still
* on but is still trying fallback strategies. * trying fallback strategies.
*/ */
internal function reportLogonTribulations (cause :LogonError) :void internal function reportLogonTribulations (cause :LogonError) :void
{ {
@@ -310,8 +321,8 @@ public class Client extends EventDispatcher
} }
/** /**
* Called by the invocation director when it successfully subscribes * Called by the invocation director when it successfully subscribes to the client object
* to the client object immediately following logon. * immediately following logon.
*/ */
public function gotClientObject (clobj :ClientObject) :void 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 * Called by the invocation director if it fails to subscribe to the client object after logon.
* client object after logon.
*/ */
public function getClientObjectFailed (cause :Error) :void 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 * Called by the invocation director when it discovers that the client object has changed.
* object has changed.
*/ */
protected function clientObjectDidChange (clobj :ClientObject) :void 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 // and let our invocation director know we're logged off
_invdir.cleanup(); _invdir.cleanup();
// if this was due to a logon error, we can notify our listeners // if this was due to a logon error, we can notify our listeners now that we're cleaned up:
// now that we're cleaned up: they may want to retry logon on // they may want to retry logon on another port, or something
// another port, or something
if (logonError != null) { if (logonError != null) {
notifyObservers(ClientEvent.CLIENT_FAILED_TO_LOGON, logonError); notifyObservers(ClientEvent.CLIENT_FAILED_TO_LOGON, logonError);
} else { } else {
@@ -1,3 +1,6 @@
//
// $Id$
package com.threerings.presents.net { package com.threerings.presents.net {
import com.threerings.io.ObjectInputStream; import com.threerings.io.ObjectInputStream;
@@ -13,7 +16,7 @@ public class AuthRequest extends UpstreamMessage
_creds = creds; _creds = creds;
_version = version; _version = version;
_bootGroups = new TypedArray("[Ljava.lang.String;"); _bootGroups = new TypedArray("[Ljava.lang.String;");
_bootGroups.concat(bootGroups); _bootGroups.addAll(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