예제 #1
0
        /* generates code like:
         *  public void TargetTest (NetworkConnection conn, int param)
         *  {
         *      NetworkWriter writer = new NetworkWriter ();
         *      writer.WritePackedUInt32 ((uint)param);
         *      base.SendTargetRPCInternal (conn, typeof(class), "TargetTest", val);
         *  }
         *  public void CallTargetTest (NetworkConnection conn, int param)
         *  {
         *      // whatever the user did before
         *  }
         *
         *  or if optional:
         *  public void TargetTest (int param)
         *  {
         *      NetworkWriter writer = new NetworkWriter ();
         *      writer.WritePackedUInt32 ((uint)param);
         *      base.SendTargetRPCInternal (null, typeof(class), "TargetTest", val);
         *  }
         *  public void CallTargetTest (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 TargetTest with CallTargetTest
         *
         *  This method moves all the user's code into the "CallTargetRpc" 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 ProcessTargetRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute targetRpcAttr)
        {
            MethodDefinition rpc = MethodProcessor.SubstituteMethod(td, md);

            ILProcessor worker = md.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(worker);

            NetworkBehaviourProcessor.WriteCreateWriter(worker);

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

            string rpcName = md.Name;

            // invoke SendInternal and return
            // this
            worker.Emit(OpCodes.Ldarg_0);
            if (HasNetworkConnectionParameter(md))
            {
                // connection
                worker.Emit(OpCodes.Ldarg_1);
            }
            else
            {
                // null
                worker.Emit(OpCodes.Ldnull);
            }
            worker.Emit(OpCodes.Ldtoken, td);
            // invokerClass
            worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
            worker.Emit(OpCodes.Ldstr, rpcName);
            // writer
            worker.Emit(OpCodes.Ldloc_0);
            worker.Emit(OpCodes.Ldc_I4, targetRpcAttr.GetField("channel", 0));
            worker.Emit(OpCodes.Callvirt, WeaverTypes.sendTargetRpcInternal);

            NetworkBehaviourProcessor.WriteRecycleWriter(worker);

            worker.Emit(OpCodes.Ret);

            return(rpc);
        }
예제 #2
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 "CallRpc" 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 clientRpcAttr)
        {
            MethodDefinition rpc = MethodProcessor.SubstituteMethod(td, md);

            ILProcessor worker = md.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(worker);

            if (Editor.Weaver.Weaver.GenerateLogErrors)
            {
                worker.Emit(OpCodes.Ldstr, "Call ClientRpc function " + md.Name);
                worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference);
            }

            NetworkBehaviourProcessor.WriteCreateWriter(worker);

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

            string rpcName      = md.Name;
            int    channel      = clientRpcAttr.GetField("channel", 0);
            bool   includeOwner = clientRpcAttr.GetField("includeOwner", true);

            // invoke SendInternal and return
            // this
            worker.Emit(OpCodes.Ldarg_0);
            worker.Emit(OpCodes.Ldtoken, td);
            // invokerClass
            worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
            worker.Emit(OpCodes.Ldstr, rpcName);
            // writer
            worker.Emit(OpCodes.Ldloc_0);
            worker.Emit(OpCodes.Ldc_I4, channel);
            // includeOwner ? 1 : 0
            worker.Emit(includeOwner ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
            worker.Emit(OpCodes.Callvirt, WeaverTypes.sendRpcInternal);

            NetworkBehaviourProcessor.WriteRecycleWriter(worker);

            worker.Emit(OpCodes.Ret);

            return(rpc);
        }
예제 #3
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 "CallCmd" 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 commandAttr)
        {
            MethodDefinition cmd = MethodProcessor.SubstituteMethod(td, md);

            ILProcessor worker = md.Body.GetILProcessor();

            NetworkBehaviourProcessor.WriteSetupLocals(worker);

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

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

            string cmdName           = md.Name;
            int    channel           = commandAttr.GetField("channel", 0);
            bool   requiresAuthority = commandAttr.GetField("requiresAuthority", true);

            // invoke internal send and return
            // load 'base.' to call the SendCommand function with
            worker.Emit(OpCodes.Ldarg_0);
            worker.Emit(OpCodes.Ldtoken, td);
            // invokerClass
            worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
            worker.Emit(OpCodes.Ldstr, cmdName);
            // writer
            worker.Emit(OpCodes.Ldloc_0);
            worker.Emit(OpCodes.Ldc_I4, channel);
            // requiresAuthority ? 1 : 0
            worker.Emit(requiresAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
            worker.Emit(OpCodes.Call, WeaverTypes.sendCommandInternal);

            NetworkBehaviourProcessor.WriteRecycleWriter(worker);

            worker.Emit(OpCodes.Ret);
            return(cmd);
        }