Use the new ObjectMarshaller.
Note that the default value of the encodeArrayElements has changed to reflect the more general-purpose use. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@351 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -33,10 +33,8 @@ import flash.events.MouseEvent;
|
|||||||
import flash.display.DisplayObject;
|
import flash.display.DisplayObject;
|
||||||
import flash.display.InteractiveObject;
|
import flash.display.InteractiveObject;
|
||||||
|
|
||||||
import flash.utils.IExternalizable;
|
|
||||||
import flash.utils.ByteArray;
|
import flash.utils.ByteArray;
|
||||||
import flash.utils.Dictionary;
|
import flash.utils.Dictionary;
|
||||||
import flash.utils.getQualifiedSuperclassName;
|
|
||||||
|
|
||||||
import com.threerings.io.TypedArray;
|
import com.threerings.io.TypedArray;
|
||||||
|
|
||||||
@@ -46,6 +44,7 @@ import com.threerings.util.Integer;
|
|||||||
import com.threerings.util.Iterator;
|
import com.threerings.util.Iterator;
|
||||||
import com.threerings.util.MessageBundle;
|
import com.threerings.util.MessageBundle;
|
||||||
import com.threerings.util.Name;
|
import com.threerings.util.Name;
|
||||||
|
import com.threerings.util.ObjectMarshaller;
|
||||||
import com.threerings.util.StringUtil;
|
import com.threerings.util.StringUtil;
|
||||||
import com.threerings.util.Wrapped;
|
import com.threerings.util.Wrapped;
|
||||||
|
|
||||||
@@ -84,7 +83,6 @@ import com.threerings.ezgame.data.EZGameObject;
|
|||||||
import com.threerings.ezgame.data.PropertySetEvent;
|
import com.threerings.ezgame.data.PropertySetEvent;
|
||||||
import com.threerings.ezgame.data.PropertySetListener;
|
import com.threerings.ezgame.data.PropertySetListener;
|
||||||
import com.threerings.ezgame.data.UserCookie;
|
import com.threerings.ezgame.data.UserCookie;
|
||||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the backend of the game.
|
* Manages the backend of the game.
|
||||||
@@ -248,7 +246,7 @@ public class GameControlBackend
|
|||||||
validateConnected();
|
validateConnected();
|
||||||
validatePropertyChange(propName, value, index);
|
validatePropertyChange(propName, value, index);
|
||||||
|
|
||||||
var encoded :Object = EZObjectMarshaller.encode(value, (index == -1));
|
var encoded :Object = ObjectMarshaller.encode(value, (index == -1));
|
||||||
_ezObj.ezGameService.setProperty(
|
_ezObj.ezGameService.setProperty(
|
||||||
_ctx.getClient(), propName, encoded, index,
|
_ctx.getClient(), propName, encoded, index,
|
||||||
false, null, createLoggingConfirmListener("setProperty"));
|
false, null, createLoggingConfirmListener("setProperty"));
|
||||||
@@ -263,8 +261,8 @@ public class GameControlBackend
|
|||||||
validateConnected();
|
validateConnected();
|
||||||
validatePropertyChange(propName, value, index);
|
validatePropertyChange(propName, value, index);
|
||||||
|
|
||||||
var encodedValue :Object = EZObjectMarshaller.encode(value, (index == -1));
|
var encodedValue :Object = ObjectMarshaller.encode(value, (index == -1));
|
||||||
var encodedTestValue :Object = EZObjectMarshaller.encode(testValue, (index == -1));
|
var encodedTestValue :Object = ObjectMarshaller.encode(testValue, (index == -1));
|
||||||
_ezObj.ezGameService.setProperty(
|
_ezObj.ezGameService.setProperty(
|
||||||
_ctx.getClient(), propName, encodedValue, index,
|
_ctx.getClient(), propName, encodedValue, index,
|
||||||
true, encodedTestValue, createLoggingConfirmListener("setProperty"));
|
true, encodedTestValue, createLoggingConfirmListener("setProperty"));
|
||||||
@@ -288,7 +286,7 @@ public class GameControlBackend
|
|||||||
validateName(messageName);
|
validateName(messageName);
|
||||||
validateValue(value);
|
validateValue(value);
|
||||||
|
|
||||||
var encoded :Object = EZObjectMarshaller.encode(value, false);
|
var encoded :Object = ObjectMarshaller.encode(value, false);
|
||||||
_ezObj.ezGameService.sendMessage(_ctx.getClient(),
|
_ezObj.ezGameService.sendMessage(_ctx.getClient(),
|
||||||
messageName, encoded, playerId,
|
messageName, encoded, playerId,
|
||||||
createLoggingConfirmListener("sendMessage"));
|
createLoggingConfirmListener("sendMessage"));
|
||||||
@@ -409,7 +407,7 @@ public class GameControlBackend
|
|||||||
var uc :UserCookie =
|
var uc :UserCookie =
|
||||||
(_ezObj.userCookies.get(playerId) as UserCookie);
|
(_ezObj.userCookies.get(playerId) as UserCookie);
|
||||||
if (uc != null) {
|
if (uc != null) {
|
||||||
callback(EZObjectMarshaller.decode(uc.cookie));
|
callback(ObjectMarshaller.decode(uc.cookie));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,7 +432,7 @@ public class GameControlBackend
|
|||||||
validateConnected();
|
validateConnected();
|
||||||
validateValue(cookie);
|
validateValue(cookie);
|
||||||
var ba :ByteArray =
|
var ba :ByteArray =
|
||||||
(EZObjectMarshaller.encode(cookie, false) as ByteArray);
|
(ObjectMarshaller.encode(cookie, false) as ByteArray);
|
||||||
if (ba.length > MAX_USER_COOKIE) {
|
if (ba.length > MAX_USER_COOKIE) {
|
||||||
// not saved!
|
// not saved!
|
||||||
return false;
|
return false;
|
||||||
@@ -544,7 +542,7 @@ public class GameControlBackend
|
|||||||
validateValue(values);
|
validateValue(values);
|
||||||
|
|
||||||
var encodedValues :TypedArray =
|
var encodedValues :TypedArray =
|
||||||
(EZObjectMarshaller.encode(values) as TypedArray);
|
(ObjectMarshaller.encode(values, true) as TypedArray);
|
||||||
|
|
||||||
_ezObj.ezGameService.addToCollection(
|
_ezObj.ezGameService.addToCollection(
|
||||||
_ctx.getClient(), collName, encodedValues, clearExisting,
|
_ctx.getClient(), collName, encodedValues, clearExisting,
|
||||||
@@ -721,47 +719,7 @@ public class GameControlBackend
|
|||||||
*/
|
*/
|
||||||
protected function validateValue (value :Object) :void
|
protected function validateValue (value :Object) :void
|
||||||
{
|
{
|
||||||
if (value == null) {
|
ObjectMarshaller.validateValue(value);
|
||||||
return;
|
|
||||||
|
|
||||||
} else if (value is IExternalizable) {
|
|
||||||
throw new ArgumentError(
|
|
||||||
"IExternalizable is not yet supported");
|
|
||||||
|
|
||||||
} else if (value is Array) {
|
|
||||||
if (ClassUtil.getClassName(value) != "Array") {
|
|
||||||
// We can't allow arrays to be serialized as IExternalizables
|
|
||||||
// because we need to know element values (opaquely) on the
|
|
||||||
// server. Also, we don't allow other types because we wouldn't
|
|
||||||
// create the right class on the other side.
|
|
||||||
throw new ArgumentError(
|
|
||||||
"Custom array subclasses are not supported");
|
|
||||||
}
|
|
||||||
// then, continue on with the sub-properties check (below)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
var type :String = typeof(value);
|
|
||||||
if (type == "number" || type == "string" || type == "boolean" ) {
|
|
||||||
// kosher!
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value is ByteArray) {
|
|
||||||
return; // kosher
|
|
||||||
}
|
|
||||||
var clazz :Class = ClassUtil.getClass(value);
|
|
||||||
var clazzparentname :String = getQualifiedSuperclassName(clazz);
|
|
||||||
var rootclass :Boolean = (clazzparentname == null);
|
|
||||||
if (! rootclass) {
|
|
||||||
throw new ArgumentError(
|
|
||||||
"Non-simple properties may not be set.");
|
|
||||||
}
|
|
||||||
// fall through and verify the object's sub-properties
|
|
||||||
}
|
|
||||||
|
|
||||||
// check sub-properties (of arrays and objects)
|
|
||||||
for each (var arrValue :Object in (value as Array)) {
|
|
||||||
validateValue(arrValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -900,7 +858,7 @@ public class GameControlBackend
|
|||||||
if (EZGameObject.USER_MESSAGE == name) {
|
if (EZGameObject.USER_MESSAGE == name) {
|
||||||
var args :Array = event.getArgs();
|
var args :Array = event.getArgs();
|
||||||
callUserCode("messageReceived_v1", (args[0] as String),
|
callUserCode("messageReceived_v1", (args[0] as String),
|
||||||
EZObjectMarshaller.decode(args[1]));
|
ObjectMarshaller.decode(args[1]));
|
||||||
|
|
||||||
} else if (EZGameObject.GAME_CHAT == name) {
|
} else if (EZGameObject.GAME_CHAT == name) {
|
||||||
// this is chat send by the game, let's route it like
|
// this is chat send by the game, let's route it like
|
||||||
@@ -925,7 +883,7 @@ public class GameControlBackend
|
|||||||
if (msgName == event.getName()) {
|
if (msgName == event.getName()) {
|
||||||
var args :Array = event.getArgs();
|
var args :Array = event.getArgs();
|
||||||
callUserCode("messageReceived_v1", (args[0] as String),
|
callUserCode("messageReceived_v1", (args[0] as String),
|
||||||
EZObjectMarshaller.decode(args[1]));
|
ObjectMarshaller.decode(args[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -940,7 +898,7 @@ public class GameControlBackend
|
|||||||
delete _cookieCallbacks[cookie.playerId];
|
delete _cookieCallbacks[cookie.playerId];
|
||||||
for each (var fn :Function in arr) {
|
for each (var fn :Function in arr) {
|
||||||
try {
|
try {
|
||||||
fn(EZObjectMarshaller.decode(cookie.cookie));
|
fn(ObjectMarshaller.decode(cookie.cookie));
|
||||||
} catch (err :Error) {
|
} catch (err :Error) {
|
||||||
// cope
|
// cope
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import com.threerings.parlor.game.client.GameConfigurator;
|
|||||||
import com.threerings.parlor.game.data.GameConfig;
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
|
|
||||||
import com.threerings.ezgame.client.EZGameController;
|
import com.threerings.ezgame.client.EZGameController;
|
||||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A game config for a simple multiplayer ez game.
|
* A game config for a simple multiplayer ez game.
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import flash.events.Event;
|
|||||||
import flash.utils.ByteArray;
|
import flash.utils.ByteArray;
|
||||||
|
|
||||||
import com.threerings.util.Name;
|
import com.threerings.util.Name;
|
||||||
|
import com.threerings.util.ObjectMarshaller;
|
||||||
|
|
||||||
import com.threerings.io.ObjectInputStream;
|
import com.threerings.io.ObjectInputStream;
|
||||||
import com.threerings.io.ObjectOutputStream;
|
import com.threerings.io.ObjectOutputStream;
|
||||||
@@ -36,8 +37,6 @@ import com.threerings.presents.dobj.DSet;
|
|||||||
import com.threerings.parlor.game.data.GameObject;
|
import com.threerings.parlor.game.data.GameObject;
|
||||||
import com.threerings.parlor.turn.data.TurnGameObject;
|
import com.threerings.parlor.turn.data.TurnGameObject;
|
||||||
|
|
||||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
|
||||||
|
|
||||||
public class EZGameObject extends GameObject
|
public class EZGameObject extends GameObject
|
||||||
implements TurnGameObject
|
implements TurnGameObject
|
||||||
{
|
{
|
||||||
@@ -142,7 +141,7 @@ public class EZGameObject extends GameObject
|
|||||||
var count :int = ins.readInt();
|
var count :int = ins.readInt();
|
||||||
while (count-- > 0) {
|
while (count-- > 0) {
|
||||||
var key :String = ins.readUTF();
|
var key :String = ins.readUTF();
|
||||||
var value :Object = EZObjectMarshaller.decode(ins.readObject());
|
var value :Object = ObjectMarshaller.decode(ins.readObject());
|
||||||
_props[key] = value;
|
_props[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,12 @@ import com.threerings.io.ObjectInputStream;
|
|||||||
import com.threerings.io.ObjectOutputStream;
|
import com.threerings.io.ObjectOutputStream;
|
||||||
import com.threerings.io.Streamer;
|
import com.threerings.io.Streamer;
|
||||||
|
|
||||||
|
import com.threerings.util.ObjectMarshaller;
|
||||||
import com.threerings.util.StringBuilder;
|
import com.threerings.util.StringBuilder;
|
||||||
|
|
||||||
import com.threerings.presents.dobj.DObject;
|
import com.threerings.presents.dobj.DObject;
|
||||||
import com.threerings.presents.dobj.NamedEvent;
|
import com.threerings.presents.dobj.NamedEvent;
|
||||||
|
|
||||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a property change on the actionscript object we
|
* Represents a property change on the actionscript object we
|
||||||
* use in FlashGameObject.
|
* use in FlashGameObject.
|
||||||
@@ -86,7 +85,7 @@ public class PropertySetEvent extends NamedEvent
|
|||||||
{
|
{
|
||||||
super.readObject(ins);
|
super.readObject(ins);
|
||||||
_index = ins.readInt();
|
_index = ins.readInt();
|
||||||
_data = EZObjectMarshaller.decode(ins.readObject());
|
_data = ObjectMarshaller.decode(ins.readObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
// from interface Streamable
|
// from interface Streamable
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
// Vilya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
|
||||||
// http://www.threerings.net/code/vilya/
|
|
||||||
//
|
|
||||||
// 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.ezgame.util {
|
|
||||||
|
|
||||||
import flash.net.ObjectEncoding;
|
|
||||||
|
|
||||||
import flash.system.ApplicationDomain;
|
|
||||||
|
|
||||||
import flash.utils.ByteArray;
|
|
||||||
import flash.utils.Endian;
|
|
||||||
|
|
||||||
import com.threerings.io.TypedArray;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods for transferring flash properties via
|
|
||||||
* the presents dobj system.
|
|
||||||
*/
|
|
||||||
public class EZObjectMarshaller
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Encode the specified object as either a byte[] or a byte[][] if it
|
|
||||||
* is an array. The specific mechanism of encoding is not important,
|
|
||||||
* as long as decode returns a clone of the original object.
|
|
||||||
*
|
|
||||||
* Currently, cycles in the object graph are preserved on the other end.
|
|
||||||
* TODO: serialize IExternalizable implementations, and take
|
|
||||||
* into account the ApplicationDomain.
|
|
||||||
*/
|
|
||||||
public static function encode (
|
|
||||||
obj :Object, encodeArrayElements :Boolean = true) :Object
|
|
||||||
{
|
|
||||||
if (obj == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (encodeArrayElements && obj is Array) {
|
|
||||||
var src :Array = (obj as Array);
|
|
||||||
var dest :TypedArray = TypedArray.create(ByteArray);
|
|
||||||
for each (var o :Object in src) {
|
|
||||||
dest.push(encode(o, false));
|
|
||||||
}
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Our own encoding, that takes into account
|
|
||||||
// the ApplicationDomain
|
|
||||||
var bytes :ByteArray = new ByteArray();
|
|
||||||
bytes.endian = Endian.BIG_ENDIAN;
|
|
||||||
bytes.objectEncoding = ObjectEncoding.AMF3;
|
|
||||||
bytes.writeObject(obj);
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function decode (encoded :Object) :Object
|
|
||||||
{
|
|
||||||
if (encoded == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (encoded is TypedArray) {
|
|
||||||
var src :TypedArray = (encoded as TypedArray);
|
|
||||||
var dest :Array = [];
|
|
||||||
for each (var b :ByteArray in src) {
|
|
||||||
dest.push(decode(b));
|
|
||||||
}
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
var bytes :ByteArray = (encoded as ByteArray);
|
|
||||||
// re-set the position in case we're decoding the actual same byte
|
|
||||||
// array used to encode (and not a network reconstruction)
|
|
||||||
bytes.position = 0;
|
|
||||||
|
|
||||||
// TODO: Our own decoding, that takes into account
|
|
||||||
// the ApplicationDomain
|
|
||||||
bytes.endian = Endian.BIG_ENDIAN;
|
|
||||||
bytes.objectEncoding = ObjectEncoding.AMF3;
|
|
||||||
return bytes.readObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user