Tuesday, March 19, 2013

Photon server and Flash (Games)

At start I was very exited about Photon being fast C++ written server with C# wrapper, with Flash SDK and even more when I saw example at sebaslab .  Checking the code at first I was even more happy that Flash - Photon are using AMF. But that was it.

I found that communication is done in kind of different way of  how Adobe have encourage using it and how its used in BlaseDS for Java and FluorineFX for .NET.
First I found that SDK is using Dictionary key/values pairs to transport data from Flash to Photon. For example you need to create Dictionary

var dictionary:Dictionary=new Dictionary();
dictionary[123]=new Actor2(3);
dictionary[122]={x:1111,y:"bbb"};


Key values can be bytes(0 -127) or Strings but String wouldn't help you engage auto reflection mechanism on Photon side( commented later). If you want to optimize bit code you need to call sendOperation(...) Function and send [key,value,key2,value2....] sendOperation(operationCode,[123,new Actor,122,{x:111,y:"bbb"}].. cos all your dictionaries would be converted to dynamic objects.
    public class Actor2
    {
       
            private var mActorNo:int=3333;
           
            public var testNumber:Number=1111.33;
           
            //public var vec:Vector.=new Vector.([1,2,3]);
            public var testArray:Array=[{x:1,y:3},3];
            
            public var testString:String="test_String";
            
            public var data:Date=new Date();
            
            public function Actor2(num:int)
            {
                mActorNo=num;
            }// end function
            
            
            
            
            public function setActorNo(param1:int) : void
            {
                mActorNo = param1;
                return;
            }// end function
            
        
    }

This would be prepared in something as:
["testNumber",1111.33,"testArray",["x",1,"y",3,3],"date",....
packed into the message(I woudn't not now comment about how the message is compose but will focus on message data) and send as AMF bytes. 



I personally doubt that such manual mechanism of mapping object attributes is better then Adobe serialization/deseralisation  by implementing of flash.utils.IExternalizable into your class object. 
Exit Games Flash SDK:

 1. Doesn't serialize private variables. Adobe shows clearly how you could decide what to serialize what not by using implementing IExternizable

2.Doesn't serialize sub/sub objects...even using Dictionary[Dictionary[Dictionary...way of doing this ex. public var testArray:Array=[{x:1,y:3},new Actor2(3)];

 3.Doesn't serialize Vector (connection closed cos of InvalidDataType exception) public var vec:Vector.=new Vector.([1,2,3]); On the server side you can forget of reconstructing of Actor2 object as we expect using AMF communication and Photon would return. Every AS3 Object would be converted into C# HashTable and every AS3 Array would be converted into C# object[]



Try to use normal way of serializing object for AMF communication returned (connection closed cos of InvalidDataType exception)

package photon_trace
{
    import flash.utils.IDataInput;
    import flash.utils.IDataOutput;
    import flash.utils.IExternalizable;

    [RemoteClass(alias="photon_trace.Actor")]
    public class Actor implements IExternalizable
    {
       
            private var mActorNo:int=3333;
           
            public var testNumber:Number=1111.33;
           
            //public var vec:Vector.=new Vector.([1,2,3]);
            public var testArray:Array=[1,2,3];
           
            public var testString:String="test_String";
           
            public var data:Date=new Date();
           
            public function Actor()
            {
               
            }// end function
           
           
            public function writeExternal(output:IDataOutput):void
            { 
                output.writeInt(mActorNo); 
            } 
            public function readExternal(input:IDataInput):void { mActorNo = input.readInt();  } 
           
            public function getActorNo() : int
            {
                return mActorNo;
            }// end function
           
            public function setActorNo(param1:int) : void
            {
                mActorNo = param1;
                return;
            }// end function
           
       
    }
}

In order to achieve somekind of auto deserialisation/reflection on Photon side,  you need to use byte as keys as ["testNumber",1111.33.... wouldn't be mapped.
but [bytekey,value... ex.  [111,1111.33... would be as key 111 maps to DataMemeber Code 111 in Operation, so some kind of mapping keys table with same values, kept at Flash and Photon side. O My I would like to back to old slow String parsing JSON.



namespace HelloPhoton
{
    class MyOperation:Operation
    {

        public MyOperation(IRpcProtocol protocol, OperationRequest request)
        : base(protocol, request)
         {
         }

        

        [DataMember(Code = (byte)111, IsOptional = false)]
        public float testNumber { get; set; }
        
    }
}
I also tried to add custom types handling serialization by using

 var typeRegistred = Photon.SocketServer.Protocol.TryRegisterCustomType(typeof(Actor), (byte)101, SerializeAMF, DeserializeAMF);

found in so scarce documentation/forums and not succeed.






Let say we send now response from Photon server to Flash client.

namespace HelloPhoton
{
    public class MyResponse
    {
        
        [DataMember(Code = (byte)33, IsOptional = false)]
        public string testText { get; set; }

        //[DataMember(Code = (byte)34, IsOptional = false)]
        //public IList testList { get; set; }//ArrayList isn't supported


        [DataMember(Code = (byte)34, IsOptional = false)]
        public Hashtable testHash { get; set; }
    }
} 
On Flash side you would get Dictionary with [33]=somestring, [34]=Array[1,2,3..,so no info about the class object. Also I couldn't put sub object(myItem done similar as MyResponse) in HashTable without Photon throwing error. And top of the cake is reply of Tobias Lead Client Engineer at Exit Games:

 "Re: Hashtable in another Hashtable" by Tobias » Thu Sep 20, 2012 5:35 pm We always have trouble with supporting Flash fully, due to it's limitations with types, so nested Hashtables are most likely affected by this. Can you work around this? Sadly, I can't promise we can do something about it really soon."

Due to Limitations with types? What types are missing? Guys in Fluorine had not problems with any C# (.NET) types and Flash types .Am I missing something? I don't even want to think about RemoteObjects and that could I invoke C# Command. Hello! anybody home :). My opinion is if you support platform you support it seriously as serious company other then that is wasting investors time and losing the clients.

1 comment:

  1. It was nice unblock game . Very informative and expressive .things are easily play online at
    Y8

    ReplyDelete