public static MethodDefinition ProcessRpcInvoke(TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc) { MethodDefinition rpc = new MethodDefinition( Weaver.InvokeRpcPrefix + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, WeaverTypes.Import(typeof(void))); ILProcessor worker = rpc.Body.GetILProcessor(); Instruction label = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(worker, md.Name, label, "RPC"); // setup for reader worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Castclass, td)); if (!NetworkBehaviourProcessor.ReadArguments(md, worker, RemoteCallType.ClientRpc)) { return(null); } // invoke actual command function worker.Append(worker.Create(OpCodes.Callvirt, rpcCallFunc)); worker.Append(worker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters); td.Methods.Add(rpc); return(rpc); }
public static MethodDefinition ProcessRpcInvoke(TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc) { var rpc = new MethodDefinition( RpcPrefix + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); ILProcessor rpcWorker = rpc.Body.GetILProcessor(); Instruction label = rpcWorker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(rpcWorker, md.Name, label, "RPC"); // setup for reader rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); rpcWorker.Append(rpcWorker.Create(OpCodes.Castclass, td)); if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(md, rpcWorker, false)) { return(null); } // invoke actual command function rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, rpcCallFunc)); rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters); td.Methods.Add(rpc); return(rpc); }
public static MethodDefinition ProcessRpcInvoke(WeaverTypes weaverTypes, Writers writers, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed) { string rpcName = Weaver.GenerateMethodName(Weaver.InvokeRpcPrefix, md); MethodDefinition rpc = new MethodDefinition(rpcName, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, weaverTypes.Import(typeof(void))); ILProcessor worker = rpc.Body.GetILProcessor(); Instruction label = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(worker, weaverTypes, md.Name, label, "RPC"); // setup for reader worker.Emit(OpCodes.Ldarg_0); worker.Emit(OpCodes.Castclass, td); if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.ClientRpc, ref WeavingFailed)) { return(null); } // invoke actual command function worker.Emit(OpCodes.Callvirt, rpcCallFunc); worker.Emit(OpCodes.Ret); NetworkBehaviourProcessor.AddInvokeParameters(weaverTypes, rpc.Parameters); td.Methods.Add(rpc); return(rpc); }
public static MethodDefinition ProcessEventInvoke(TypeDefinition td, EventDefinition ed) { // find the field that matches the event FieldDefinition eventField = null; foreach (FieldDefinition fd in td.Fields) { if (fd.FullName == ed.FullName) { eventField = fd; break; } } if (eventField == null) { Weaver.DLog(td, "ERROR: no event field?!"); Weaver.fail = true; return(null); } MethodDefinition cmd = new MethodDefinition("InvokeSyncEvent" + ed.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); ILProcessor cmdWorker = cmd.Body.GetILProcessor(); Instruction label1 = cmdWorker.Create(OpCodes.Nop); Instruction label2 = cmdWorker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(cmdWorker, ed.Name, label1, "Event"); // null event check cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, td)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField)); cmdWorker.Append(cmdWorker.Create(OpCodes.Brtrue, label2)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); cmdWorker.Append(label2); // setup reader cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, td)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField)); // read the event arguments MethodReference invoke = Resolvers.ResolveMethod(eventField.FieldType, Weaver.scriptDef, "Invoke"); if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(td, invoke.Resolve(), cmdWorker, false)) { return(null); } // invoke actual event delegate function cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, invoke)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters); return(cmd); }
public static MethodDefinition ProcessEventInvoke(TypeDefinition td, EventDefinition ed) { // find the field that matches the event FieldDefinition eventField = null; foreach (var fd in td.Fields) { if (fd.FullName == ed.FullName) { eventField = fd; break; } } if (eventField == null) { Weaver.Error($"{td} not found. Did you declare the event?"); return(null); } var cmd = new MethodDefinition("InvokeSyncEvent" + ed.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); var cmdWorker = cmd.Body.GetILProcessor(); var label1 = cmdWorker.Create(OpCodes.Nop); var label2 = cmdWorker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(cmdWorker, ed.Name, label1, "Event"); // null event check cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, td)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField)); cmdWorker.Append(cmdWorker.Create(OpCodes.Brtrue, label2)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); cmdWorker.Append(label2); // setup reader cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, td)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField)); // read the event arguments var invoke = Resolvers.ResolveMethod(eventField.FieldType, Weaver.CurrentAssembly, "Invoke"); if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(invoke.Resolve(), cmdWorker, false)) { return(null); } // invoke actual event delegate function cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, invoke)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters); return(cmd); }
public static MethodDefinition ProcessEventInvoke(TypeDefinition td, EventDefinition ed) { // find the field that matches the event FieldDefinition eventField = null; foreach (FieldDefinition fd in td.Fields) { if (fd.FullName == ed.FullName) { eventField = fd; break; } } if (eventField == null) { Weaver.Error($"event field not found for {ed.Name}. Did you declare it as an event?", ed); return(null); } MethodDefinition cmd = new MethodDefinition(Weaver.InvokeRpcPrefix + ed.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); ILProcessor worker = cmd.Body.GetILProcessor(); Instruction label1 = worker.Create(OpCodes.Nop); Instruction label2 = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(worker, ed.Name, label1, "Event"); // null event check worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Castclass, td)); worker.Append(worker.Create(OpCodes.Ldfld, eventField)); worker.Append(worker.Create(OpCodes.Brtrue, label2)); worker.Append(worker.Create(OpCodes.Ret)); worker.Append(label2); // setup reader worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Castclass, td)); worker.Append(worker.Create(OpCodes.Ldfld, eventField)); // read the event arguments MethodReference invoke = Resolvers.ResolveMethod(eventField.FieldType, Weaver.CurrentAssembly, "Invoke"); if (!NetworkBehaviourProcessor.ReadArguments(invoke.Resolve(), worker, RemoteCallType.SyncEvent)) { return(null); } // invoke actual event delegate function worker.Append(worker.Create(OpCodes.Callvirt, invoke)); worker.Append(worker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters); return(cmd); }
public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed) { string trgName = Weaver.GenerateMethodName(Weaver.InvokeRpcPrefix, md); MethodDefinition rpc = new MethodDefinition(trgName, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, weaverTypes.Import(typeof(void))); ILProcessor worker = rpc.Body.GetILProcessor(); Instruction label = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(worker, weaverTypes, md.Name, label, "TargetRPC"); // setup for reader worker.Emit(OpCodes.Ldarg_0); worker.Emit(OpCodes.Castclass, td); // NetworkConnection parameter is optional if (HasNetworkConnectionParameter(md)) { // on server, the NetworkConnection parameter is a connection to client. // when the rpc is invoked on the client, it still has the same // function signature. we pass in the connection to server, // which is cleaner than just passing null) //NetworkClient.readyconnection // // TODO // a) .connectionToServer = best solution. no doubt. // b) NetworkClient.connection for now. add TODO to not use static later. worker.Emit(OpCodes.Call, weaverTypes.NetworkClientConnectionReference); } // process reader parameters and skip first one if first one is NetworkConnection if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.TargetRpc, ref WeavingFailed)) { return(null); } // invoke actual command function worker.Emit(OpCodes.Callvirt, rpcCallFunc); worker.Emit(OpCodes.Ret); NetworkBehaviourProcessor.AddInvokeParameters(weaverTypes, rpc.Parameters); td.Methods.Add(rpc); return(rpc); }
public static MethodDefinition ProcessTargetRpcInvoke(TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc) { var rpc = new MethodDefinition(RpcProcessor.RpcPrefix + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); ILProcessor rpcWorker = rpc.Body.GetILProcessor(); Instruction label = rpcWorker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(rpcWorker, md.Name, label, "TargetRPC"); // setup for reader rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); rpcWorker.Append(rpcWorker.Create(OpCodes.Castclass, td)); // NetworkConnection parameter is optional bool hasNetworkConnection = HasNetworkConnectionParameter(md); if (hasNetworkConnection) { //client.connection rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.BehaviorConnectionToServerReference)); } // process reader parameters and skip first one if first one is NetworkConnection if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(md, rpcWorker, hasNetworkConnection)) { return(null); } // invoke actual command function rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, rpcCallFunc)); rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters); td.Methods.Add(rpc); return(rpc); }
/// <summary> /// Generates a skeleton for an RPC /// </summary> /// <param name="td"></param> /// <param name="method"></param> /// <param name="cmdCallFunc"></param> /// <returns>The newly created skeleton method</returns> /// <remarks> /// Generates code like this: /// <code> /// protected static void Skeleton_Test(NetworkBehaviour obj, NetworkReader reader, NetworkConnection senderConnection) /// { /// if (!obj.netIdentity.server.active) /// { /// return; /// } /// ((ShipControl) obj).UserCode_Test(reader.ReadSingle(), (int) reader.ReadPackedUInt32()); /// } /// </code> /// </remarks> public static MethodDefinition GenerateSkeleton(MethodDefinition md, MethodDefinition userCodeFunc, CustomAttribute clientRpcAttr) { var rpc = new MethodDefinition( MethodProcessor.SkeletonPrefix + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, WeaverTypes.Import(typeof(void))); ILProcessor worker = rpc.Body.GetILProcessor(); Instruction label = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(worker, md.Name, label, "RPC"); // setup for reader worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Castclass, md.DeclaringType)); // NetworkConnection parameter is only required for Client.Connection Client target = clientRpcAttr.GetField("target", Client.Observers); bool hasNetworkConnection = target == Client.Connection && HasNetworkConnectionParameter(md); if (hasNetworkConnection) { //client.connection worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Call, WeaverTypes.BehaviorConnectionToServerReference)); } if (!NetworkBehaviourProcessor.ReadArguments(md, worker, hasNetworkConnection)) { return(null); } // invoke actual ServerRpc function worker.Append(worker.Create(OpCodes.Callvirt, userCodeFunc)); worker.Append(worker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters); md.DeclaringType.Methods.Add(rpc); return(rpc); }
public static MethodDefinition ProcessTargetRpcInvoke(TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc) { MethodDefinition rpc = new MethodDefinition(Weaver.InvokeRpcPrefix + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, WeaverTypes.voidType); ILProcessor worker = rpc.Body.GetILProcessor(); Instruction label = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteClientActiveCheck(worker, md.Name, label, "TargetRPC"); // setup for reader worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Castclass, td)); // NetworkConnection parameter is optional if (HasNetworkConnectionParameter(md)) { // if call has NetworkConnection write clients connection as first arg //ClientScene.readyconnection worker.Append(worker.Create(OpCodes.Call, WeaverTypes.ReadyConnectionReference)); } // process reader parameters and skip first one if first one is NetworkConnection if (!NetworkBehaviourProcessor.ReadArguments(md, worker, RemoteCallType.TargetRpc)) { return(null); } // invoke actual command function worker.Append(worker.Create(OpCodes.Callvirt, rpcCallFunc)); worker.Append(worker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters); td.Methods.Add(rpc); 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); }