Example #1
0
        protected void SendServerRpcInternal(Type invokeClass, string cmdName, NetworkWriter writer, int channelId, bool requireAuthority = true)
        {
            // this was in Weaver before
            // NOTE: we could remove this later to allow calling Cmds on Server
            //       to avoid Wrapper functions. a lot of people requested this.
            if (!Client.Active)
            {
                throw new InvalidOperationException($"ServerRpc Function {cmdName} called on server without an active client.");
            }

            // local players can always send ServerRpcs, regardless of authority, other objects must have authority.
            if (requireAuthority && !(IsLocalPlayer || HasAuthority))
            {
                throw new UnauthorizedAccessException($"Trying to send ServerRpc for object without authority. {invokeClass.ToString()}.{cmdName}");
            }

            if (Client.Connection == null)
            {
                throw new InvalidOperationException("Send ServerRpc attempted with no client running [client=" + ConnectionToServer + "].");
            }

            // construct the message
            var message = new ServerRpcMessage
            {
                netId          = NetId,
                componentIndex = ComponentIndex,
                // type+func so Inventory.RpcUse != Equipment.RpcUse
                functionHash = RemoteCallHelper.GetMethodHash(invokeClass, cmdName),
                // segment to avoid reader allocations
                payload = writer.ToArraySegment()
            };

            _ = Client.SendAsync(message, channelId);
        }
Example #2
0
        /// <summary>
        /// Handle ServerRpc from specific player, this could be one of multiple players on a single client
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="msg"></param>
        void OnServerRpcMessage(INetworkConnection conn, ServerRpcMessage msg)
        {
            if (!Spawned.TryGetValue(msg.netId, out NetworkIdentity identity) || identity == null)
            {
                logger.LogWarning("Spawned object not found when handling ServerRpc message [netId=" + msg.netId + "]");
                return;
            }

            ServerRpcInfo ServerRpcInfo = identity.GetServerRpcInfo(msg.componentIndex, msg.functionHash);

            // ServerRpcs can be for player objects, OR other objects with client-authority
            // -> so if this connection's controller has a different netId then
            //    only allow the ServerRpc if clientAuthorityOwner
            if (ServerRpcInfo.requireAuthority && identity.ConnectionToClient != conn)
            {
                logger.LogWarning("ServerRpc for object without authority [netId=" + msg.netId + "]");
                return;
            }

            if (logger.LogEnabled())
            {
                logger.Log("OnServerRpcMessage for netId=" + msg.netId + " conn=" + conn);
            }

            using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload))
                identity.HandleRemoteCall(msg.componentIndex, msg.functionHash, MirrorInvokeType.ServerRpc, networkReader, conn);
        }
        protected internal void SendServerRpcInternal(Type invokeClass, string cmdName, NetworkWriter writer, int channelId, bool requireAuthority = true)
        {
            ValidateServerRpc(invokeClass, cmdName, requireAuthority);

            // construct the message
            var message = new ServerRpcMessage
            {
                netId          = NetId,
                componentIndex = ComponentIndex,
                // type+func so Inventory.RpcUse != Equipment.RpcUse
                functionHash = RemoteCallHelper.GetMethodHash(invokeClass, cmdName),
                // segment to avoid reader allocations
                payload = writer.ToArraySegment()
            };

            Client.SendAsync(message, channelId).Forget();
        }
        protected internal UniTask <T> SendServerRpcWithReturn <T>(Type invokeClass, string cmdName, NetworkWriter writer, int channelId, bool requireAuthority = true)
        {
            ValidateServerRpc(invokeClass, cmdName, requireAuthority);

            (UniTask <T> task, int id) = ClientObjectManager.CreateReplyTask <T>();

            // construct the message
            var message = new ServerRpcMessage
            {
                netId          = NetId,
                componentIndex = ComponentIndex,
                replyId        = id,
                // type+func so Inventory.RpcUse != Equipment.RpcUse
                functionHash = RemoteCallHelper.GetMethodHash(invokeClass, cmdName),
                // segment to avoid reader allocations
                payload = writer.ToArraySegment()
            };

            Client.SendAsync(message, channelId).Forget();

            return(task);
        }
Example #5
0
        /// <summary>
        /// Handle ServerRpc from specific player, this could be one of multiple players on a single client
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="msg"></param>
        void OnServerRpcMessage(INetworkConnection conn, ServerRpcMessage msg)
        {
            if (!server.Spawned.TryGetValue(msg.netId, out NetworkIdentity identity) || identity is null)
            {
                if (logger.WarnEnabled())
                {
                    logger.LogWarning("Spawned object not found when handling ServerRpc message [netId=" + msg.netId + "]");
                }
                return;
            }
            Skeleton skeleton = RemoteCallHelper.GetSkeleton(msg.functionHash);

            if (skeleton.invokeType != MirrorInvokeType.ServerRpc)
            {
                throw new MethodInvocationException($"Invalid ServerRpc for id {msg.functionHash}");
            }

            // ServerRpcs can be for player objects, OR other objects with client-authority
            // -> so if this connection's controller has a different netId then
            //    only allow the ServerRpc if clientAuthorityOwner
            if (skeleton.cmdRequireAuthority && identity.ConnectionToClient != conn)
            {
                if (logger.WarnEnabled())
                {
                    logger.LogWarning("ServerRpc for object without authority [netId=" + msg.netId + "]");
                }
                return;
            }

            if (logger.LogEnabled())
            {
                logger.Log("OnServerRpcMessage for netId=" + msg.netId + " conn=" + conn);
            }

            using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload))
                identity.HandleRemoteCall(skeleton, msg.componentIndex, networkReader, conn, msg.replyId);
        }