/*
         *  // generates code like:
         *  public void CmdThrust(float thrusting, int spin)
         *  {
         *      NetworkWriter networkWriter = new NetworkWriter();
         *      networkWriter.Write(thrusting);
         *      networkWriter.WritePackedUInt32((uint)spin);
         *      base.SendCommandInternal(cmdName, networkWriter, cmdName);
         *  }
         *
         *  public void CallCmdThrust(float thrusting, int spin)
         *  {
         *      // whatever the user was doing before
         *  }
         *
         *  Originally HLAPI put the send message code inside the Call function
         *  and then proceeded to replace every call to CmdTrust with CallCmdTrust
         *
         *  This method moves all the user's code into the "Call" method
         *  and replaces the body of the original method with the send message code.
         *  This way we do not need to modify the code anywhere else,  and this works
         *  correctly in dependent assemblies
         */
        public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
        {
            MethodDefinition cmd = new MethodDefinition("Call" + md.Name,
                                                        MethodAttributes.Public | MethodAttributes.HideBySig,
                                                        Weaver.voidType);

            // add parameters
            foreach (ParameterDefinition pd in md.Parameters)
            {
                cmd.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
            }

            // move the old body to the new function
            MethodBody newBody = cmd.Body;

            cmd.Body = md.Body;
            md.Body  = newBody;

            ILProcessor cmdWorker = md.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(cmdWorker);

            if (Weaver.GenerateLogErrors)
            {
                cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, "Call Command function " + md.Name));
                cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.logErrorReference));
            }

            // NetworkWriter writer = new NetworkWriter();
            NetworkBehaviourProcessor.WriteCreateWriter(cmdWorker);

            // write all the arguments that the user passed to the Cmd call
            if (!NetworkBehaviourProcessor.WriteArguments(cmdWorker, md, false))
            {
                return(null);
            }

            string cmdName = md.Name;
            int    index   = cmdName.IndexOf(CmdPrefix);

            if (index > -1)
            {
                cmdName = cmdName.Substring(CmdPrefix.Length);
            }

            // invoke internal send and return
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));                                 // load 'base.' to call the SendCommand function with
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldtoken, td));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, cmdName));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0));                                 // writer
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.sendCommandInternal));

            NetworkBehaviourProcessor.WriteRecycleWriter(cmdWorker);

            cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));

            return(cmd);
        }
        /* generates code like:
         * public void CallTargetTest (NetworkConnection conn, int param)
         * {
         *  NetworkWriter writer = new NetworkWriter ();
         *  writer.WritePackedUInt32 ((uint)param);
         *  base.SendTargetRPCInternal (conn, typeof(class), "TargetTest", val);
         * }
         *
         * or if optional:
         * public void CallTargetTest (int param)
         * {
         *  NetworkWriter writer = new NetworkWriter ();
         *  writer.WritePackedUInt32 ((uint)param);
         *  base.SendTargetRPCInternal (null, typeof(class), "TargetTest", val);
         * }
         */
        public static MethodDefinition ProcessTargetRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
        {
            MethodDefinition rpc = new MethodDefinition("Call" + md.Name, MethodAttributes.Public |
                                                        MethodAttributes.HideBySig,
                                                        Weaver.voidType);

            // add parameters
            foreach (ParameterDefinition pd in md.Parameters)
            {
                rpc.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
            }

            ILProcessor rpcWorker = rpc.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(rpcWorker);

            NetworkBehaviourProcessor.WriteCreateWriter(rpcWorker);

            // NetworkConnection parameter is optional
            bool hasNetworkConnection = HasNetworkConnectionParameter(md);

            // write all the arguments that the user passed to the TargetRpc call
            // (skip first one if first one is NetworkConnection)
            if (!NetworkBehaviourProcessor.WriteArguments(rpcWorker, md, hasNetworkConnection))
            {
                return(null);
            }

            string rpcName = md.Name;
            int    index   = rpcName.IndexOf(TargetRpcPrefix);

            if (index > -1)
            {
                rpcName = rpcName.Substring(TargetRpcPrefix.Length);
            }

            // invoke SendInternal and return
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); // this
            if (HasNetworkConnectionParameter(md))
            {
                rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_1)); // connection
            }
            else
            {
                rpcWorker.Append(rpcWorker.Create(OpCodes.Ldnull)); // null
            }
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldtoken, td));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0));                                 // writer
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal));

            NetworkBehaviourProcessor.WriteRecycleWriter(rpcWorker);

            rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));

            return(rpc);
        }
        /*
         * generates code like:
         *
         *  public void RpcTest (int param)
         *  {
         *      NetworkWriter writer = new NetworkWriter ();
         *      writer.WritePackedUInt32((uint)param);
         *      base.SendRPCInternal(typeof(class),"RpcTest", writer, 0);
         *  }
         *  public void CallRpcTest (int param)
         *  {
         *      // whatever the user did before
         *  }
         *
         *  Originally HLAPI put the send message code inside the Call function
         *  and then proceeded to replace every call to RpcTest with CallRpcTest
         *
         *  This method moves all the user's code into the "Call" method
         *  and replaces the body of the original method with the send message code.
         *  This way we do not need to modify the code anywhere else,  and this works
         *  correctly in dependent assemblies
         */
        public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
        {
            MethodDefinition rpc = new MethodDefinition("Call" + md.Name, MethodAttributes.Public |
                                                        MethodAttributes.HideBySig,
                                                        Weaver.voidType);

            // add paramters
            foreach (ParameterDefinition pd in md.Parameters)
            {
                rpc.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
            }

            // move the old body to the new function
            MethodBody newBody = rpc.Body;

            rpc.Body = md.Body;
            md.Body  = newBody;

            ILProcessor rpcWorker = md.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(rpcWorker);

            NetworkBehaviourProcessor.WriteCreateWriter(rpcWorker);

            // write all the arguments that the user passed to the Rpc call
            if (!NetworkBehaviourProcessor.WriteArguments(rpcWorker, md, false))
            {
                return(null);
            }

            string rpcName = md.Name;
            int    index   = rpcName.IndexOf(RpcPrefix);

            if (index > -1)
            {
                rpcName = rpcName.Substring(RpcPrefix.Length);
            }

            // invoke SendInternal and return
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0));                                 // this
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldtoken, td));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0));                                 // writer
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendRpcInternal));

            NetworkBehaviourProcessor.WriteRecycleWriter(rpcWorker);

            rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));

            return(rpc);
        }
Example #4
0
        /*
         *  // generates code like:
         *  public void CmdThrust(float thrusting, int spin)
         *  {
         *      NetworkWriter networkWriter = new NetworkWriter();
         *      networkWriter.Write(thrusting);
         *      networkWriter.WritePackedUInt32((uint)spin);
         *      base.SendCommandInternal(cmdName, networkWriter, cmdName);
         *  }
         *
         *  public void CallCmdThrust(float thrusting, int spin)
         *  {
         *      // whatever the user was doing before
         *  }
         *
         *  Originally HLAPI put the send message code inside the Call function
         *  and then proceeded to replace every call to CmdTrust with CallCmdTrust
         *
         *  This method moves all the user's code into the "Call" method
         *  and replaces the body of the original method with the send message code.
         *  This way we do not need to modify the code anywhere else,  and this works
         *  correctly in dependent assemblies
         */
        public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
        {
            MethodDefinition cmd = MethodProcessor.SubstituteMethod(md, "Call" + md.Name);

            ILProcessor cmdWorker = md.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(cmdWorker);

            if (Weaver.GenerateLogErrors)
            {
                cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, "Call Command function " + md.Name));
                cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.logErrorReference));
            }

            // NetworkWriter writer = new NetworkWriter();
            NetworkBehaviourProcessor.WriteCreateWriter(cmdWorker);

            // write all the arguments that the user passed to the Cmd call
            if (!NetworkBehaviourProcessor.WriteArguments(cmdWorker, md, false))
            {
                return(null);
            }

            string cmdName = md.Name;
            int    index   = cmdName.IndexOf(CmdPrefix);

            if (index > -1)
            {
                cmdName = cmdName.Substring(CmdPrefix.Length);
            }

            // invoke internal send and return
            // load 'base.' to call the SendCommand function with
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldtoken, td));
            // invokerClass
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, cmdName));
            // writer
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.sendCommandInternal));

            NetworkBehaviourProcessor.WriteRecycleWriter(cmdWorker);

            cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));

            return(cmd);
        }
Example #5
0
        public static MethodDefinition ProcessEventCall(TypeDefinition td, EventDefinition ed, CustomAttribute ca)
        {
            MethodReference  invoke = Resolvers.ResolveMethod(ed.EventType, Weaver.CurrentAssembly, "Invoke");
            MethodDefinition evt    = new MethodDefinition("Call" + ed.Name, MethodAttributes.Public |
                                                           MethodAttributes.HideBySig,
                                                           Weaver.voidType);

            // add paramters
            foreach (ParameterDefinition pd in invoke.Parameters)
            {
                evt.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
            }

            ILProcessor evtWorker = evt.Body.GetILProcessor();
            Instruction label     = evtWorker.Create(OpCodes.Nop);

            NetworkBehaviourProcessor.WriteSetupLocals(evtWorker);

            NetworkBehaviourProcessor.WriteServerActiveCheck(evtWorker, ed.Name, label, "Event");

            NetworkBehaviourProcessor.WriteCreateWriter(evtWorker);

            // write all the arguments that the user passed to the syncevent
            if (!NetworkBehaviourProcessor.WriteArguments(evtWorker, invoke.Resolve(), false))
            {
                return(null);
            }

            // invoke interal send and return
            // this
            evtWorker.Append(evtWorker.Create(OpCodes.Ldarg_0));
            evtWorker.Append(evtWorker.Create(OpCodes.Ldtoken, td));
            // invokerClass
            evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
            evtWorker.Append(evtWorker.Create(OpCodes.Ldstr, ed.Name));
            // writer
            evtWorker.Append(evtWorker.Create(OpCodes.Ldloc_0));
            evtWorker.Append(evtWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.sendEventInternal));

            NetworkBehaviourProcessor.WriteRecycleWriter(evtWorker);

            evtWorker.Append(evtWorker.Create(OpCodes.Ret));

            return(evt);
        }
Example #6
0
        /*
         * generates code like:
         *
         *  public void RpcTest (int param)
         *  {
         *      NetworkWriter writer = new NetworkWriter ();
         *      writer.WritePackedUInt32((uint)param);
         *      base.SendRPCInternal(typeof(class),"RpcTest", writer, 0);
         *  }
         *  public void CallRpcTest (int param)
         *  {
         *      // whatever the user did before
         *  }
         *
         *  Originally HLAPI put the send message code inside the Call function
         *  and then proceeded to replace every call to RpcTest with CallRpcTest
         *
         *  This method moves all the user's code into the "Call" method
         *  and replaces the body of the original method with the send message code.
         *  This way we do not need to modify the code anywhere else,  and this works
         *  correctly in dependent assemblies
         */
        public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
        {
            MethodDefinition rpc = MethodProcessor.SubstituteMethod(md, "Call" + md.Name);

            ILProcessor rpcWorker = md.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(rpcWorker);

            NetworkBehaviourProcessor.WriteCreateWriter(rpcWorker);

            // write all the arguments that the user passed to the Rpc call
            if (!NetworkBehaviourProcessor.WriteArguments(rpcWorker, md, false))
            {
                return(null);
            }

            string rpcName = md.Name;
            int    index   = rpcName.IndexOf(RpcPrefix);

            if (index > -1)
            {
                rpcName = rpcName.Substring(RpcPrefix.Length);
            }

            // invoke SendInternal and return
            // this
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldtoken, td));
            // invokerClass
            rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName));
            // writer
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendRpcInternal));

            NetworkBehaviourProcessor.WriteRecycleWriter(rpcWorker);

            rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));

            return(rpc);
        }
Example #7
0
        /* generates code like:
         * public void CallTargetTest (NetworkConnection conn, int param)
         * {
         *  if (!NetworkServer.get_active ()) {
         *      Debug.LogError((object)"TargetRPC Function TargetTest called on client.");
         *  } else if (((?)conn) is ULocalConnectionToServer) {
         *      Debug.LogError((object)"TargetRPC Function TargetTest called on connection to server");
         *  } else {
         *      NetworkWriter writer = new NetworkWriter ();
         *      writer.WritePackedUInt32 ((uint)param);
         *      base.SendTargetRPCInternal (conn, typeof(class), "TargetTest", val);
         *  }
         * }
         */
        public static MethodDefinition ProcessTargetRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
        {
            MethodDefinition rpc = new MethodDefinition("Call" + md.Name, MethodAttributes.Public |
                                                        MethodAttributes.HideBySig,
                                                        Weaver.voidType);

            // add paramters
            foreach (ParameterDefinition pd in md.Parameters)
            {
                rpc.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
            }

            ILProcessor rpcWorker = rpc.Body.GetILProcessor();
            Instruction label     = rpcWorker.Create(OpCodes.Nop);

            NetworkBehaviourProcessor.WriteSetupLocals(rpcWorker);

            NetworkBehaviourProcessor.WriteServerActiveCheck(rpcWorker, md.Name, label, "TargetRPC Function");

            Instruction labelConnectionCheck = rpcWorker.Create(OpCodes.Nop);

            // check specifically for ULocalConnectionToServer so a host is not trying to send
            // an TargetRPC to the "server" from it's local client.
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_1));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Isinst, Weaver.ULocalConnectionToServerType));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Brfalse, labelConnectionCheck));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, string.Format("TargetRPC Function {0} called on connection to server", md.Name)));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.logErrorReference));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));
            rpcWorker.Append(labelConnectionCheck);

            NetworkBehaviourProcessor.WriteCreateWriter(rpcWorker);

            // write all the arguments that the user passed to the TargetRpc call
            if (!NetworkBehaviourProcessor.WriteArguments(rpcWorker, md, "TargetRPC", true))
            {
                return(null);
            }

            var rpcName = md.Name;
            int index   = rpcName.IndexOf(k_TargetRpcPrefix);

            if (index > -1)
            {
                rpcName = rpcName.Substring(k_TargetRpcPrefix.Length);
            }

            // invoke SendInternal and return
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0));                                 // this
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_1));                                 // connection
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldtoken, td));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0));                                 // writer
            rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal));

            rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));

            return(rpc);
        }
Example #8
0
        /*
         *  // generates code like:
         *  public void CallCmdThrust(float thrusting, int spin)
         *  {
         *      Debug.LogError("Call Command function CmdThrust");
         *      if (!NetworkClient.active)
         *      {
         *          Debug.LogError("Command function CmdThrust called on server.");
         *          return;
         *      }
         *
         *      if (isServer)
         *      {
         *          // we are ON the server, invoke directly
         *          CmdThrust(thrusting, spin);
         *          return;
         *      }
         *
         *      NetworkWriter networkWriter = new NetworkWriter();
         *      networkWriter.Write(thrusting);
         *      networkWriter.WritePackedUInt32((uint)spin);
         *      base.SendCommandInternal(cmdName, networkWriter, cmdName);
         *  }
         */
        public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
        {
            MethodDefinition cmd = new MethodDefinition("Call" + md.Name, MethodAttributes.Public |
                                                        MethodAttributes.HideBySig,
                                                        Weaver.voidType);

            // add paramters
            foreach (ParameterDefinition pd in md.Parameters)
            {
                cmd.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
            }

            ILProcessor cmdWorker = cmd.Body.GetILProcessor();
            Instruction label     = cmdWorker.Create(OpCodes.Nop);

            NetworkBehaviourProcessor.WriteSetupLocals(cmdWorker);

            if (Weaver.generateLogErrors)
            {
                cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, "Call Command function " + md.Name));
                cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.logErrorReference));
            }

            NetworkBehaviourProcessor.WriteClientActiveCheck(cmdWorker, md.Name, label, "Command function");

            // local client check
            Instruction localClientLabel = cmdWorker.Create(OpCodes.Nop);

            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.UBehaviourIsServer));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Brfalse, localClientLabel));

            // call the cmd function directly.
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
            for (int i = 0; i < md.Parameters.Count; i++)
            {
                cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg, i + 1));
            }
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, md));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));
            cmdWorker.Append(localClientLabel);

            // NetworkWriter writer = new NetworkWriter();
            NetworkBehaviourProcessor.WriteCreateWriter(cmdWorker);

            // write all the arguments that the user passed to the Cmd call
            if (!NetworkBehaviourProcessor.WriteArguments(cmdWorker, md, "Command", false))
            {
                return(null);
            }

            var cmdName = md.Name;
            int index   = cmdName.IndexOf(k_CmdPrefix);

            if (index > -1)
            {
                cmdName = cmdName.Substring(k_CmdPrefix.Length);
            }

            // invoke interal send and return
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));                                 // load 'base.' to call the SendCommand function with
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldtoken, td));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, cmdName));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0));                                 // writer
            cmdWorker.Append(cmdWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
            cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.sendCommandInternal));

            cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));

            return(cmd);
        }