示例#1
0
        public static void Prefix(ref Player __instance)
        {
            // This is only for clients. Add a welcome message to the chat box displaying the status of VChat.
            if (!HasSentServerPluginStatusMessage)
            {
                var chat = Chat.instance;
                if (chat != null)
                {
                    // Notify the server connection status.
                    if (GreetingMessage.HasLocalPlayerGreetedToServer && GreetingMessage.HasLocalPlayerReceivedGreetingFromServer)
                    {
                        chat.AddString($"<color=lime>[{VChatPlugin.Name}] Connected to the server-wide instance of {VChatPlugin.Name}, server version of {GreetingMessage.ServerVersion}.</color>");
                    }
                    else if (GreetingMessage.HasLocalPlayerGreetedToServer && !GreetingMessage.HasLocalPlayerReceivedGreetingFromServer)
                    {
                        chat.AddString($"<color=white>[{VChatPlugin.Name}] was not found on the server, messages sent to the global chat can only be seen by players with {VChatPlugin.Name} installed.</color>");
                    }
                    else
                    {
                        chat.AddString($"<color=red>[{VChatPlugin.Name}] Has encountered an issue greeting the server.</color>");
                    }
                }
                else
                {
                    VChatPlugin.LogError($"Could not write the VChat welcome message because Chat is not yet initialised.");
                }

                HasSentServerPluginStatusMessage = true;
            }
        }
示例#2
0
        /// <summary>
        /// Adds a command to the collection.
        /// </summary>
        public void AddCommand(PluginCommand pluginCommand)
        {
            lock (_lock)
            {
                // First check for duplicate command names.
                foreach (var command in Commands)
                {
                    string duplicateCommandName = null;
                    foreach (var commandName1 in pluginCommand.CommandNames)
                    {
                        foreach (var commandName2 in command.CommandNames)
                        {
                            if (string.Equals(commandName1, commandName2, StringComparison.CurrentCultureIgnoreCase))
                            {
                                VChatPlugin.LogError($"Command with the name \"{Prefix}{duplicateCommandName}\" already exists, types {command.Type} and {pluginCommand.Type}.");
                                duplicateCommandName = commandName1;
                                break;
                            }
                        }
                    }
                }

                // Add the command, we currently don't care if a duplicate command name is found.
                _commands.Add(pluginCommand);
            }
        }
示例#3
0
 /// <summary>
 /// Send a VChat greeting message to the server
 /// </summary>
 public static void SendToServer()
 {
     if (!ZNet.m_isServer)
     {
         var parameters = new object[] { VChatPlugin.Version };
         ZRoutedRpc.instance.InvokeRoutedRPC(ZNet.instance.GetServerPeer().m_uid, GreetingHashName, parameters);
         HasLocalPlayerGreetedToServer = true;
     }
     else
     {
         VChatPlugin.LogError($"Cannot send the greeing to ourself, are we missing a server check?");
     }
 }
        public static bool Prefix(ref ZRoutedRpc __instance, ref RoutedRPCData data)
        {
            if (ZNet.m_isServer && data?.m_methodHash == GlobalMessages.TalkerSayHashCode)
            {
                // Read local say chat messages for users not connected to VChat.
                // Messages that fit the global chat command name will be redirected as global chat messages.
                if (GreetingMessage.PeerInfo.TryGetValue(data.m_senderPeerID, out GreetingMessagePeerInfo peerInfo) &&
                    !peerInfo.HasReceivedGreeting)
                {
                    try
                    {
                        var senderPeer = ZNet.instance.GetPeer(data.m_senderPeerID);
                        var package    = new ZPackage(data.m_parameters.GetArray());
                        var ctype      = package.ReadInt();
                        var playerName = package.ReadString();
                        var text       = package.ReadString();

                        if (ctype == (int)Talker.Type.Normal)
                        {
                            var globalChatCommand = VChatPlugin.CommandHandler.FindCommand(PluginCommandType.SendGlobalMessage);
                            if (VChatPlugin.CommandHandler.IsValidCommandString(text, globalChatCommand, out text))
                            {
                                VChatPlugin.Log($"Redirecting local message to global chat from peer {data.m_senderPeerID} \"({senderPeer?.m_playerName})\" with message \"{text}\".");

                                // Redirect this message to the global chat channel.
                                foreach (var peer in ZNet.instance.GetConnectedPeers())
                                {
                                    // Exclude the sender, otherwise it'd probably just be annoying.
                                    if (peer.m_uid != data.m_senderPeerID)
                                    {
                                        GlobalMessages.SendGlobalMessageToPeer(peer.m_uid, (int)GlobalMessageType.RedirectedGlobalMessage, senderPeer?.m_refPos ?? new Vector3(), senderPeer?.m_playerName ?? playerName, text);
                                    }
                                }

                                // Intercept message so that other connected users won't receive the same message twice.
                                data.m_methodHash = GlobalMessages.InterceptedSayHashCode;
                                return(false);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        VChatPlugin.LogError($"Error reading Talker.Say message for unconnected VChat user ({data.m_senderPeerID}): {ex}");
                    }
                }
            }

            return(true);
        }
示例#5
0
        /// <summary>
        /// Attempt to find the command based on the type, this should technically never fail.
        /// </summary>
        public PluginCommand FindCommand(PluginCommandType type)
        {
            lock (_lock)
            {
                foreach (var command in Commands)
                {
                    if (command.Type == type)
                    {
                        return(command);
                    }
                }
            }

            VChatPlugin.LogError($"Could not find the command for {type}, is this a new unhandled command?");
            return(null);
        }
示例#6
0
 /// <summary>
 /// Triggered when the server receives a global message from a client .
 /// </summary>
 /// <remarks>Player name and position are primarily here for future work, player aliases for example.</remarks>
 /// <param name="senderId">The peer id of the sender</param>
 /// <param name="pos">The reported position</param>
 /// <param name="type">Reserved for future use</param>
 /// <param name="callerName">The reported player name</param>
 /// <param name="text">the message, without a playername or formatting.</param>
 private static void OnGlobalMessage_Server(long senderId, Vector3 pos, int type, string callerName, string text)
 {
     if (senderId != ZNet.instance.GetServerPeer()?.m_uid)
     {
         var globalMessageType = (GlobalMessageType)type;
         if (globalMessageType == GlobalMessageType.StandardMessage || globalMessageType == GlobalMessageType.RedirectedGlobalMessage)
         {
             try
             {
                 // Sender should always be found but who knows what can happen within a few milliseconds, though I bet its still cached should that player disconnect.. safety first.
                 // We simply apply the position and player name the server knows rather than the reported values first.
                 var peer = ZRoutedRpc.instance?.GetPeer(senderId);
                 if (peer?.m_server == false)
                 {
                     // Loop through every connected peer and redirect the received message, including the original sender because the code is currently set so that the client knows that it's been sent.
                     foreach (var connectedPeer in ZNet.instance.GetConnectedPeers())
                     {
                         if (connectedPeer != null && !connectedPeer.m_server && connectedPeer.IsReady() && connectedPeer.m_socket?.IsConnected() == true)
                         {
                             VChatPlugin.Log($"Routing global message to peer {connectedPeer.m_uid} \"({connectedPeer.m_playerName})\" with message \"{text}\".");
                             SendGlobalMessageToPeer(connectedPeer.m_uid, type, peer?.m_refPos ?? pos, peer?.m_playerName ?? callerName, text);
                         }
                     }
                 }
                 else
                 {
                     VChatPlugin.LogWarning($"Received a global chat message from a peer identified as a server, id {senderId} \"{peer.m_playerName}\"");
                 }
             }
             catch (Exception ex)
             {
                 VChatPlugin.LogError($"Failed to InvokeRoutedRPC for global message ({senderId}|{text}): {ex}");
             }
         }
         else
         {
             VChatPlugin.LogWarning($"A global message type with value of {type} could not be parsed. Please check if there are any updates available.");
         }
     }
     else
     {
         VChatPlugin.LogWarning($"Received a greeting from a peer with the server id...");
     }
 }
示例#7
0
        /// <summary>
        /// Send a global message to the server.
        /// </summary>
        public static void SendGlobalMessageToServer(string text, GlobalMessageType type = GlobalMessageType.StandardMessage)
        {
            var localPlayer = Player.m_localPlayer;

            if (localPlayer != null)
            {
                long peerId = ZRoutedRpc.Everybody;

                // If server-sided VChat is found, send the message directly to the server.
                var serverPeer = ZNet.instance?.GetServerPeer();
                if (GreetingMessage.HasLocalPlayerReceivedGreetingFromServer && serverPeer != null)
                {
                    peerId = ZNet.instance.GetServerPeer().m_uid;
                }

                var parameters = new object[] { localPlayer.GetHeadPoint(), (int)type, localPlayer.GetPlayerName(), text };
                ZRoutedRpc.instance.InvokeRoutedRPC(peerId, GlobalChatHashName, parameters);
            }
            else
            {
                VChatPlugin.LogError($"Could not send global message because the player is undefined (text: \"{text}\").");
            }
        }