/// <summary> Processes a response to an RPC assignment request. The assigned id and method name are added to the LocalRpcs dictionary. </summary> internal void ReceiveAssignmentResponse(NetMessage netMessage, NetConnection connection) { if (!connection.IsServer && !connection.IsPeer) { return; } var id = (ushort)netMessage.Parameters[0]; var methodName = (string)netMessage.Parameters[1]; if (RpcInfoCache.Exists(methodName) && !idToName.ContainsKey(id)) { idToName.Add(id, methodName); if (!nameToId.ContainsKey(methodName)) { nameToId.Add(methodName, id); } } else { NetLog.Error("Cannot assign local RPC. ID: " + id + " MethodName: " + methodName); } if (idToName.Count == RpcInfoCache.Count) { Socket.SendRequirementsMet(connection); } }
internal bool Dispatch(NetMessage message, NetConnection connection, MethodInfo method, object instance) { List <Type> paramTypes = RpcInfoCache.ParamTypes(method.Name); if (paramTypes.Count >= message.Parameters.Length) { return(false); } if (method.ReturnType == typeof(IEnumerator) || method.ReturnType == typeof(void)) { return(false); } ushort requestId = (ushort)message.Parameters[message.Parameters.Length - 1]; object[] culledParams = new object[paramTypes.Count]; for (int i = 0; i < paramTypes.Count; i++) { culledParams[i] = message.Parameters[i]; } message.Parameters = culledParams; object result = method.Invoke(instance, message.Parameters); connection.Send(NetMessage.Create((ushort)Cmd.RequestResponse, message.ViewId, new object[] { requestId, true, result }, true)); return(true); }
/// <summary> Registers an instance of a MonoBehaviour to receive RPCs not associated with a NetView. </summary> public void RegisterRpcListener(MonoBehaviour listener) { foreach (KeyValuePair <string, RpcMethodInfo> cachedRpc in RpcInfoCache.RpcMethods()) { if (!cachedRpc.Value.MethodInfoLookup.ContainsKey(listener.GetType())) { continue; } rpcObjectInstances.Add(cachedRpc.Value.Name, listener); } }
/// <summary> Awake is a Unity convention. Unity invokes this method first when instantiated. </summary> private void Awake() { Application.runInBackground = true; Application.targetFrameRate = TargetFrameRate; Request = new RequestDispatcher(this); Rpc = new RpcDispatcher(this); RpcInfoCache.RpcMethods(); RegisterCommandParams(); }
/// <summary> Called by the server to generate IDs for local RPCs. </summary> internal void AssignLocalRpcs() { int i = 0; foreach (KeyValuePair <string, RpcMethodInfo> kvp in RpcInfoCache.RpcMethods()) { for (i++; i < 1800; i++) { if (HasName((ushort)i)) { continue; } idToName.Add((ushort)i, kvp.Value.Name); nameToId.Add(kvp.Value.Name, (ushort)i); break; } } }
/// <summary> Post-instantiation configuration of NetView. </summary> private void RegisterNetView(NetView view) { if (view.CachedRpcObjects == null) { view.SetRpcCache(RpcInfoCache.CreateInstanceLookup(view.gameObject)); } view.Scope.Trans = view.gameObject.transform; view.Socket = Socket; view.ViewManager = this; if (!ViewLookup.ContainsKey(view.Id)) { ViewLookup.Add(view.Id, view); } if (!Views.Contains(view)) { Views.Add(view); } }
/// <summary> Sends a request to the server for each local RPC method name that needs an ID assignment. </summary> internal void RequestAssignments(NetConnection connection) { foreach (string methodName in RpcInfoCache.RpcMethods().Keys) { if (HasId(methodName)) { if (!HasName(NameToId(methodName))) { idToName.Add(NameToId(methodName), methodName); } continue; } Socket.Command.Send((int)Cmd.AssignmentRequest, connection, methodName); } if (IdCount >= RpcInfoCache.Count) { Socket.SendRequirementsMet(connection); } }
/// <summary> Invokes RPC with parameters from the NetMessage. </summary> internal void Invoke(object instance, string methodName, NetMessage message, NetConnection sender) { RpcMethodInfo rpcInfo = RpcInfoCache.Get(methodName); MethodInfo method = rpcInfo.MethodInfoLookup[instance.GetType()]; if (rpcInfo.TakesRequests && Socket.Request.Dispatch(message, sender, method, instance)) { return; } if (method.ReturnType == typeof(IEnumerator)) { var coroutine = (IEnumerator)method.Invoke(instance, message.Parameters); var behaviour = (MonoBehaviour)instance; if (coroutine != null) { behaviour.StartCoroutine(coroutine); } } else { method.Invoke(instance, message.Parameters); } }
internal List <Type> ParamTypes(ushort id) { return(RpcInfoCache.ParamTypes(IdToName(id))); }
/// <summary> Returns true if the provided rpcID is associated with a method. </summary> internal bool Exists(ushort rpcId) { return(HasName(rpcId) && RpcInfoCache.Exists(IdToName(rpcId))); }
/// <summary> Returns true if the RPC method has a return value or has a NetRequest parameter. </summary> internal bool TakesRequests(ushort rpcId) { return(HasName(rpcId) && RpcInfoCache.TakesRequests(IdToName(rpcId))); }