/* * // generates code like: * protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader reader, NetworkConnection senderConnection) * { * if (!NetworkServer.active) * { * return; * } * ((ShipControl)obj).CmdThrust(reader.ReadSingle(), (int)reader.ReadPackedUInt32()); * } */ public static MethodDefinition ProcessCommandInvoke(TypeDefinition td, MethodDefinition method, MethodDefinition cmdCallFunc) { MethodDefinition cmd = new MethodDefinition(Weaver.InvokeRpcPrefix + method.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, WeaverTypes.Import(typeof(void))); ILProcessor worker = cmd.Body.GetILProcessor(); Instruction label = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteServerActiveCheck(worker, method.Name, label, "Command"); // setup for reader worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Castclass, td)); if (!NetworkBehaviourProcessor.ReadArguments(method, worker, RemoteCallType.Command)) { return(null); } AddSenderConnection(method, worker); // invoke actual command function worker.Append(worker.Create(OpCodes.Callvirt, cmdCallFunc)); worker.Append(worker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters); td.Methods.Add(cmd); return(cmd); }
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 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); }
/// <summary> /// Generates a skeleton for a ServerRpc /// </summary> /// <param name="td"></param> /// <param name="method"></param> /// <param name="userCodeFunc"></param> /// <returns>The newly created skeleton method</returns> /// <remarks> /// Generates code like this: /// <code> /// protected static void Skeleton_MyServerRpc(NetworkBehaviour obj, NetworkReader reader, NetworkConnection senderConnection) /// { /// if (!obj.netIdentity.server.active) /// { /// return; /// } /// ((ShipControl) obj).UserCode_Thrust(reader.ReadSingle(), (int) reader.ReadPackedUInt32()); /// } /// </code> /// </remarks> public static MethodDefinition GenerateSkeleton(MethodDefinition method, MethodDefinition userCodeFunc) { var cmd = new MethodDefinition(MethodProcessor.SkeletonPrefix + method.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, WeaverTypes.Import(typeof(void))); ILProcessor worker = cmd.Body.GetILProcessor(); Instruction label = worker.Create(OpCodes.Nop); NetworkBehaviourProcessor.WriteServerActiveCheck(worker, method.Name, label, "ServerRpc"); // setup for reader worker.Append(worker.Create(OpCodes.Ldarg_0)); worker.Append(worker.Create(OpCodes.Castclass, method.DeclaringType)); if (!NetworkBehaviourProcessor.ReadArguments(method, worker, false)) { return(null); } AddSenderConnection(method, worker); // invoke actual ServerRpc function worker.Append(worker.Create(OpCodes.Callvirt, userCodeFunc)); worker.Append(worker.Create(OpCodes.Ret)); NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters); method.DeclaringType.Methods.Add(cmd); 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); }
/// <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(RpcProcessor.RpcPrefix + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.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 bool hasNetworkConnection = HasNetworkConnectionParameter(md); if (hasNetworkConnection) { //ClientScene.readyconnection worker.Append(worker.Create(OpCodes.Call, Weaver.ReadyConnectionReference)); } // process reader parameters and skip first one if first one is NetworkConnection if (!NetworkBehaviourProcessor.ReadArguments(md, worker, hasNetworkConnection)) { 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); }