Created a new class BinaryMarshaller that handles incoming rpc calls, unmarshalling them automatically into the appropriate object, according to packet.Layout.Name.
 
The code for this is pretty simple:
 

    public object UnmarshallFromBinary( Packet packet )
    {
        object rpcobject = null;
        try
        {
            string RpcClassName = packet.Layout.Name ;
            rpcobject = Activator.GetObject( RpcClassName );
            ArrayList blocks = packet.Blocks();

            foreach( MemberInfo memberinfo in target.GetType().GetMembers() )
            {
                Console.WriteLine( memberinfo.Name  + " " + memberinfo.MemberType.ToString() );
                if( memberinfo.MemberType == MemberTypes.Field )
                {
                    FieldInfo fi = target.GetType().GetField( memberinfo.Name );                   
                    foreach (Block block in blocks)
                    {
                        foreach (Field field in block.Fields)
                        {
                            if (field.Layout.Name == memberinfo.Name )
                            {
                                PackSingleProperty( rpcobject, fi, field.Data );
                            }
                        }
                    }
                }
            }
        }
        catch( Exception e )
        {
            Console.WriteLine( e.ToString() );
        }
        return rpcobject;
    }

where PackSingleProperty( ... ) is:

    // Mostly this is trivial, except for strings, possible other exceptions and ObjectUpdate attributes
    // - We can tweak this to scan for custom attributes, eg for ObjectUpdate attributes
    // - uint, LLUUID, byte, and LLVector3, IPAddress, U64, ushort
    //     are all simple casts, so handled by the default SetValue( rpcobject, data )
    void PackSingleProperty( object rpcobject, FieldInfo fi, object data )
    {
        Type fieldtype = fi.FieldType;
        if( fieldtype == typeof( string ) )
        {
            fi.SetValue( rpcobject, System.Text.Encoding.UTF8.GetString((byte[])data).Replace("\0", "") );
        }
        else
        {
            fi.SetValue( rpcobject, data );
        }
    }

What this means is that now we can replace for example, in avatar.cs:

  private void InstantMessageHandler(Packet packet, Circuit circuit)
  {
   if (packet.Layout.Name == "ImprovedInstantMessage")
   {
    LLUUID FromAgentID = new LLUUID();
    LLUUID ToAgentID = new LLUUID();
    uint ParentEstateID = 0;
    LLUUID RegionID  = new LLUUID();
    LLVector3 Position = new LLVector3();
    byte Offline  = 0;
    byte Dialog   = 0;
    LLUUID ID   = new LLUUID();
    uint Timestamp  = 0;
    string AgentName = "";
    string Message  = "";
    string Bucket  = "";

    ArrayList blocks;

    blocks = packet.Blocks();

    foreach (Block block in blocks)
    {
     foreach (Field field in block.Fields)
     {
      if(field.Layout.Name == "FromAgentID")
      {
       FromAgentID = (LLUUID)field.Data;
      }
      else if(field.Layout.Name == "ToAgentID")
      {
       ToAgentID = (LLUUID)field.Data;
      }
      else if( field.Layout.Name == "ParentEstateID")
      {
       ParentEstateID = (uint)field.Data;
      }
      else if(field.Layout.Name == "RegionID")
      {
       RegionID = (LLUUID)field.Data;
      }
      else if(field.Layout.Name == "Position")
      {
       Position = (LLVector3)field.Data;
      }
      else if(field.Layout.Name == "Offline")
      {
       Offline = (byte)field.Data;
      }
      else if(field.Layout.Name == "Dialog")
      {
       Dialog = (byte)field.Data;
      }
      else if(field.Layout.Name == "ID")
      {
       ID = (LLUUID)field.Data;
      }
      else if(field.Layout.Name == "Timestamp")
      {
       Timestamp = (uint)field.Data;
      }
      else if( field.Layout.Name == "AgentName")
      {
       AgentName = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", "");
      }
      else if( field.Layout.Name == "Message")
      {
       Message = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", "");
      }
      else if( field.Layout.Name == "BinaryBucket")
      {
       Bucket = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", "");
      }
     }
    }
    OnInstantMessage(FromAgentID,ToAgentID,ParentEstateID,RegionID,Position,
     Offline,Dialog,ID,Timestamp,AgentName,Message,Bucket);
   }
  }

by simply:

  private void InstantMessageHandler(Packet packet, Circuit circuit)
  {
   if (packet.Layout.Name == "ImprovedInstantMessage")
   {
                ImprovedInstantMessage improvedinstantmessage =
                    (ImprovedInstantMessage)BinaryMarshaller.UnmarshallFromBinary( packet );
    OnInstantMessage( improvedinstantmessage );
   }
  }

Where ImprovedInstantMessage is:

public class ImprovedInstantMessage
{
    public LLUUID FromAgentID = new LLUUID();
    public LLUUID ToAgentID = new LLUUID();
    public uint ParentEstateID = 0;
    public LLUUID RegionID  = new LLUUID();
    public LLVector3 Position = new LLVector3();
    public byte Offline  = 0;
    public byte Dialog   = 0;
    public LLUUID ID   = new LLUUID();
    public uint Timestamp  = 0;
    public string FromAgentName = "";
    public string Message  = "";
    public string BinaryBucket  = "";        
 }

A LOT easier right?

 

 

_______________________________________________
libsecondlife-dev mailing list
[email protected]
https://mail.gna.org/listinfo/libsecondlife-dev

Reply via email to