public void GetDelegate() { // registerdelegate is protected, but we can use // RegisterCommandDelegate which calls RegisterDelegate int registeredHash = RemoteProcedureCalls.RegisterDelegate( typeof(NetworkBehaviourDelegateComponent), nameof(NetworkBehaviourDelegateComponent.Delegate), RemoteCallType.Command, NetworkBehaviourDelegateComponent.Delegate, false); // get handler int cmdHash = nameof(NetworkBehaviourDelegateComponent.Delegate).GetStableHashCode(); RemoteCallDelegate func = RemoteProcedureCalls.GetDelegate(cmdHash); RemoteCallDelegate expected = NetworkBehaviourDelegateComponent.Delegate; Assert.That(func, Is.EqualTo(expected)); // invalid hash should return null handler RemoteCallDelegate funcNull = RemoteProcedureCalls.GetDelegate(1234); Assert.That(funcNull, Is.Null); // clean up RemoteProcedureCalls.RemoveDelegate(registeredHash); }
// pass full function name to avoid ClassA.Func & ClassB.Func collisions internal static int RegisterDelegate(Type componentType, string functionFullName, RemoteCallType remoteCallType, RemoteCallDelegate func, bool cmdRequiresAuthority = true) { // type+func so Inventory.RpcUse != Equipment.RpcUse int hash = functionFullName.GetStableHashCode(); if (CheckIfDelegateExists(componentType, remoteCallType, func, hash)) { return(hash); } // register invoker by hash remoteCallDelegates[hash] = new Invoker { callType = remoteCallType, componentType = componentType, function = func, cmdRequiresAuthority = cmdRequiresAuthority }; return(hash); }
static bool CheckIfDelegateExists(Type componentType, RemoteCallType remoteCallType, RemoteCallDelegate func, int functionHash) { if (remoteCallDelegates.ContainsKey(functionHash)) { // something already registered this hash. // it's okay if it was the same function. Invoker oldInvoker = remoteCallDelegates[functionHash]; if (oldInvoker.AreEqual(componentType, remoteCallType, func)) { return(true); } // otherwise notify user. there is a rare chance of string // hash collisions. Debug.LogError($"Function {oldInvoker.componentType}.{oldInvoker.function.GetMethodName()} and {componentType}.{func.GetMethodName()} have the same hash. Please rename one of them"); } return(false); }
public bool AreEqual(Type componentType, RemoteCallType remoteCallType, RemoteCallDelegate invokeFunction) => this.componentType == componentType && this.callType == remoteCallType && this.function == invokeFunction;
// pass full function name to avoid ClassA.Func <-> ClassB.Func collisions // need to pass componentType to support invoking on GameObjects with // multiple components of same type with same remote call. public static void RegisterRpc(Type componentType, string functionFullName, RemoteCallDelegate func) => RegisterDelegate(componentType, functionFullName, RemoteCallType.ClientRpc, func);
// pass full function name to avoid ClassA.Func <-> ClassB.Func collisions // need to pass componentType to support invoking on GameObjects with // multiple components of same type with same remote call. public static void RegisterCommand(Type componentType, string functionFullName, RemoteCallDelegate func, bool requiresAuthority) => RegisterDelegate(componentType, functionFullName, RemoteCallType.Command, func, requiresAuthority);