internal static void ExecuteRpc()

in MRTK Tutorials/Assets/Photon/PhotonUnityNetworking/Code/PhotonNetworkPart.cs [354:655]


        internal static void ExecuteRpc(Hashtable rpcData, Player sender)
        {
            if (rpcData == null || !rpcData.ContainsKey(keyByteZero))
            {
                Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClassPun.DictionaryToString(rpcData));
                return;
            }

            // ts: updated with "flat" event data
            int netViewID = (int)rpcData[keyByteZero]; // LIMITS PHOTONVIEWS&PLAYERS
            int otherSidePrefix = 0;    // by default, the prefix is 0 (and this is not being sent)
            if (rpcData.ContainsKey(keyByteOne))
            {
                otherSidePrefix = (short)rpcData[keyByteOne];
            }


            string inMethodName;
            if (rpcData.ContainsKey(keyByteFive))
            {
                int rpcIndex = (byte)rpcData[keyByteFive];  // LIMITS RPC COUNT
                if (rpcIndex > PhotonNetwork.PhotonServerSettings.RpcList.Count - 1)
                {
                    Debug.LogError("Could not find RPC with index: " + rpcIndex + ". Going to ignore! Check PhotonServerSettings.RpcList");
                    return;
                }
                else
                {
                    inMethodName = PhotonNetwork.PhotonServerSettings.RpcList[rpcIndex];
                }
            }
            else
            {
                inMethodName = (string)rpcData[keyByteThree];
            }

            object[] arguments = null;
            if (rpcData.ContainsKey(keyByteFour))
            {
                arguments = (object[])rpcData[keyByteFour];
            }

            PhotonView photonNetview = GetPhotonView(netViewID);
            if (photonNetview == null)
            {
                int viewOwnerId = netViewID / PhotonNetwork.MAX_VIEW_IDS;
                bool owningPv = (viewOwnerId == NetworkingClient.LocalPlayer.ActorNumber);
                bool ownerSent = sender != null && viewOwnerId == sender.ActorNumber;

                if (owningPv)
                {
                    Debug.LogWarning("Received RPC \"" + inMethodName + "\" for viewID " + netViewID + " but this PhotonView does not exist! View was/is ours." + (ownerSent ? " Owner called." : " Remote called.") + " By: " + sender);
                }
                else
                {
                    Debug.LogWarning("Received RPC \"" + inMethodName + "\" for viewID " + netViewID + " but this PhotonView does not exist! Was remote PV." + (ownerSent ? " Owner called." : " Remote called.") + " By: " + sender + " Maybe GO was destroyed but RPC not cleaned up.");
                }
                return;
            }

            if (photonNetview.Prefix != otherSidePrefix)
            {
                Debug.LogError("Received RPC \"" + inMethodName + "\" on viewID " + netViewID + " with a prefix of " + otherSidePrefix + ", our prefix is " + photonNetview.Prefix + ". The RPC has been ignored.");
                return;
            }

            // Get method name
            if (string.IsNullOrEmpty(inMethodName))
            {
                Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClassPun.DictionaryToString(rpcData));
                return;
            }

            if (PhotonNetwork.LogLevel >= PunLogLevel.Full)
            {
                Debug.Log("Received RPC: " + inMethodName);
            }


            // SetReceiving filtering
            if (photonNetview.Group != 0 && !allowedReceivingGroups.Contains(photonNetview.Group))
            {
                return; // Ignore group
            }

            Type[] argumentsTypes = null;
            if (arguments != null && arguments.Length > 0)
            {
                argumentsTypes = new Type[arguments.Length];
                int i = 0;
                for (int index = 0; index < arguments.Length; index++)
                {
                    object objX = arguments[index];
                    if (objX == null)
                    {
                        argumentsTypes[i] = null;
                    }
                    else
                    {
                        argumentsTypes[i] = objX.GetType();
                    }

                    i++;
                }
            }


            int receivers = 0;
            int foundMethods = 0;
            if (!PhotonNetwork.UseRpcMonoBehaviourCache || photonNetview.RpcMonoBehaviours == null || photonNetview.RpcMonoBehaviours.Length == 0)
            {
                photonNetview.RefreshRpcMonoBehaviourCache();
            }

            for (int componentsIndex = 0; componentsIndex < photonNetview.RpcMonoBehaviours.Length; componentsIndex++)
            {
                MonoBehaviour monob = photonNetview.RpcMonoBehaviours[componentsIndex];
                if (monob == null)
                {
                    Debug.LogError("ERROR You have missing MonoBehaviours on your gameobjects!");
                    continue;
                }

                Type type = monob.GetType();

                // Get [PunRPC] methods from cache
                List<MethodInfo> cachedRPCMethods = null;
                bool methodsOfTypeInCache = monoRPCMethodsCache.TryGetValue(type, out cachedRPCMethods);

                if (!methodsOfTypeInCache)
                {
                    List<MethodInfo> entries = SupportClassPun.GetMethods(type, typePunRPC);

                    monoRPCMethodsCache[type] = entries;
                    cachedRPCMethods = entries;
                }

                if (cachedRPCMethods == null)
                {
                    continue;
                }

                // Check cache for valid methodname+arguments
                for (int index = 0; index < cachedRPCMethods.Count; index++)
                {
                    MethodInfo mInfo = cachedRPCMethods[index];
                    if (!mInfo.Name.Equals(inMethodName))
                    {
                        continue;
                    }

                    ParameterInfo[] parameters = mInfo.GetCachedParemeters();
                    foundMethods++;


                    // if we got no arguments:
                    if (arguments == null)
                    {
                        if (parameters.Length == 0)
                        {
                            receivers++;
                            object o = mInfo.Invoke((object)monob, null);
                            if (PhotonNetwork.RunRpcCoroutines)
                            {
                                IEnumerator ie = null;//o as IEnumerator;
                                if ((ie = o as IEnumerator) != null)
                                {
                                    PhotonHandler.Instance.StartCoroutine(ie);
                                }
                            }
                        }
                        else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(PhotonMessageInfo))
                        {
                            int sendTime = (int)rpcData[keyByteTwo];

                            receivers++;
                            object o = mInfo.Invoke((object)monob, new object[] { new PhotonMessageInfo(sender, sendTime, photonNetview) });
                            if (PhotonNetwork.RunRpcCoroutines)
                            {
                                IEnumerator ie = null;//o as IEnumerator;
                                if ((ie = o as IEnumerator) != null)
                                {
                                    PhotonHandler.Instance.StartCoroutine(ie);
                                }
                            }
                        }
                        continue;
                    }


                    // if there are any arguments (in the incoming call check if the method is compatible
                    if (parameters.Length == arguments.Length)
                    {
                        // Normal, PhotonNetworkMessage left out
                        if (CheckTypeMatch(parameters, argumentsTypes))
                        {
                            receivers++;
                            object o = mInfo.Invoke((object)monob, arguments);
                            if (PhotonNetwork.RunRpcCoroutines)
                            {
                                IEnumerator ie = null;//o as IEnumerator;
                                if ((ie = o as IEnumerator) != null)
                                {
                                    PhotonHandler.Instance.StartCoroutine(ie);
                                }
                            }
                        }
                        continue;
                    }

                    if (parameters.Length == arguments.Length + 1)
                    {
                        // Check for PhotonNetworkMessage being the last
                        if (parameters[parameters.Length - 1].ParameterType == typeof(PhotonMessageInfo) && CheckTypeMatch(parameters, argumentsTypes))
                        {
                            int sendTime = (int)rpcData[keyByteTwo];
                            object[] argumentsWithInfo = new object[arguments.Length + 1];
                            arguments.CopyTo(argumentsWithInfo, 0);
                            argumentsWithInfo[argumentsWithInfo.Length - 1] = new PhotonMessageInfo(sender, sendTime, photonNetview);

                            receivers++;
                            object o = mInfo.Invoke((object)monob, argumentsWithInfo);
                            if (PhotonNetwork.RunRpcCoroutines)
                            {
                                IEnumerator ie = null;//o as IEnumerator;
                                if ((ie = o as IEnumerator) != null)
                                {
                                    PhotonHandler.Instance.StartCoroutine(ie);
                                }
                            }
                        }
                        continue;
                    }

                    if (parameters.Length == 1 && parameters[0].ParameterType.IsArray)
                    {
                        receivers++;
                        object o = mInfo.Invoke((object)monob, new object[] { arguments });
                        if (PhotonNetwork.RunRpcCoroutines)
                        {
                            IEnumerator ie = null;//o as IEnumerator;
                            if ((ie = o as IEnumerator) != null)
                            {
                                PhotonHandler.Instance.StartCoroutine(ie);
                            }
                        }
                        continue;
                    }
                }
            }

            // Error handling
            if (receivers != 1)
            {
                string argsString = string.Empty;
                int argsLength = 0;
                if (argumentsTypes != null)
                {
                    argsLength = argumentsTypes.Length;
                    for (int index = 0; index < argumentsTypes.Length; index++)
                    {
                        Type ty = argumentsTypes[index];
                        if (argsString != string.Empty)
                        {
                            argsString += ", ";
                        }

                        if (ty == null)
                        {
                            argsString += "null";
                        }
                        else
                        {
                            argsString += ty.Name;
                        }
                    }
                }

                GameObject context = photonNetview != null ? photonNetview.gameObject : null;
                if (receivers == 0)
                {
                    if (foundMethods == 0)
                    {
                        // found no method that matches
                        Debug.LogErrorFormat(context, "RPC method '{0}({2})' not found on object with PhotonView {1}. Implement as non-static. Apply [PunRPC]. Components on children are not found. " +
                            "Return type must be void or IEnumerator (if you enable RunRpcCoroutines). RPCs are a one-way message.", inMethodName, netViewID, argsString);
                    }
                    else
                    {
                        // found a method but not the right arguments
                        Debug.LogErrorFormat(context, "RPC method '{0}' found on object with PhotonView {1} but has wrong parameters. Implement as '{0}({2})'. PhotonMessageInfo is optional as final parameter." +
                            "Return type must be void or IEnumerator (if you enable RunRpcCoroutines).", inMethodName, netViewID, argsString);
                    }
                }
                else
                {
                    // multiple components have the same method
                    Debug.LogErrorFormat(context, "RPC method '{0}({2})' found {3}x on object with PhotonView {1}. Only one component should implement it." +
                            "Return type must be void or IEnumerator (if you enable RunRpcCoroutines).", inMethodName, netViewID, argsString, foundMethods);
                }
            }
        }