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