/* 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); }
/* * 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); }
/* * // 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); }