Example #1
0
 public void AddChatMessage(string message, ChatMessageType type, string senderName = "", Character senderCharacter = null)
 {
     AddChatMessage(ChatMessage.Create(senderName, message, type, senderCharacter));
 }
        private void UpdateCapture()
        {
            Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
            Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
            nativeBuffer = Marshal.AllocHGlobal(VoipConfig.BUFFER_SIZE * 2);
            try
            {
                while (capturing)
                {
                    int alcError;

                    if (CanDetectDisconnect)
                    {
                        Alc.GetInteger(captureDevice, Alc.EnumConnected, out int isConnected);
                        alcError = Alc.GetError(captureDevice);
                        if (alcError != Alc.NoError)
                        {
                            throw new Exception("Failed to determine if capture device is connected: " + alcError.ToString());
                        }

                        if (isConnected == 0)
                        {
                            DebugConsole.ThrowError("Capture device has been disconnected. You can select another available device in the settings.");
                            Disconnected = true;
                            break;
                        }
                    }

                    FillBuffer();

                    alcError = Alc.GetError(captureDevice);
                    if (alcError != Alc.NoError)
                    {
                        throw new Exception("Failed to capture samples: " + alcError.ToString());
                    }

                    double maxAmplitude = 0.0f;
                    for (int i = 0; i < VoipConfig.BUFFER_SIZE; i++)
                    {
                        uncompressedBuffer[i] = (short)MathHelper.Clamp((uncompressedBuffer[i] * Gain), -short.MaxValue, short.MaxValue);
                        double sampleVal = uncompressedBuffer[i] / (double)short.MaxValue;
                        maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sampleVal));
                    }
                    double dB = Math.Min(20 * Math.Log10(maxAmplitude), 0.0);

                    LastdB = dB;
                    LastAmplitude = maxAmplitude;

                    bool allowEnqueue = overrideSound != null;
                    if (GameMain.WindowActive)
                    {
                        ForceLocal = captureTimer > 0 ? ForceLocal : GameMain.Config.UseLocalVoiceByDefault;
                        bool pttDown = false;
                        if ((PlayerInput.KeyDown(InputType.Voice) || PlayerInput.KeyDown(InputType.LocalVoice)) &&
                                GUI.KeyboardDispatcher.Subscriber == null)
                        {
                            pttDown = true;
                            if (PlayerInput.KeyDown(InputType.LocalVoice))
                            {
                                ForceLocal = true;
                            }
                            else
                            {
                                ForceLocal = false;
                            }
                        }
                        if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Activity)
                        {
                            if (dB > GameMain.Config.NoiseGateThreshold)
                            {
                                allowEnqueue = true;
                            }
                        }
                        else if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.PushToTalk)
                        {
                            if (pttDown)
                            {
                                allowEnqueue = true;
                            }
                        }
                    }

                    if (allowEnqueue || captureTimer > 0)
                    {
                        LastEnqueueAudio = DateTime.Now;
                        if (GameMain.Client?.Character != null)
                        {
                            var messageType = !ForceLocal && ChatMessage.CanUseRadio(GameMain.Client.Character, out _) ? ChatMessageType.Radio : ChatMessageType.Default;
                            GameMain.Client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
                        }
                        //encode audio and enqueue it
                        lock (buffers)
                        {
                            if (!prevCaptured) //enqueue the previous buffer if not sent to avoid cutoff
                            {
                                int compressedCountPrev = VoipConfig.Encoder.Encode(prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
                                EnqueueBuffer(compressedCountPrev);
                            }
                            int compressedCount = VoipConfig.Encoder.Encode(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
                            EnqueueBuffer(compressedCount);
                        }
                        captureTimer -= (VoipConfig.BUFFER_SIZE * 1000) / VoipConfig.FREQUENCY;
                        if (allowEnqueue)
                        {
                            captureTimer = GameMain.Config.VoiceChatCutoffPrevention;
                        }
                        prevCaptured = true;
                    }
                    else
                    {
                        captureTimer = 0;
                        prevCaptured = false;
                        //enqueue silence
                        lock (buffers)
                        {
                            EnqueueBuffer(0);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                DebugConsole.ThrowError($"VoipCapture threw an exception. Disabling capture...", e);
                capturing = false;
            }
            finally
            {
                Marshal.FreeHGlobal(nativeBuffer);
            }
        }
Example #3
0
        public static void ServerRead(IReadMessage msg, Client c)
        {
            c.KickAFKTimer = 0.0f;

            UInt16          ID   = msg.ReadUInt16();
            ChatMessageType type = (ChatMessageType)msg.ReadByte();
            string          txt;

            Character        orderTargetCharacter = null;
            Entity           orderTargetEntity    = null;
            OrderChatMessage orderMsg             = null;
            OrderTarget      orderTargetPosition  = null;

            if (type == ChatMessageType.Order)
            {
                int orderIndex = msg.ReadByte();
                orderTargetCharacter = Entity.FindEntityByID(msg.ReadUInt16()) as Character;
                orderTargetEntity    = Entity.FindEntityByID(msg.ReadUInt16()) as Entity;
                int orderOptionIndex = msg.ReadByte();
                if (msg.ReadBoolean())
                {
                    var x    = msg.ReadSingle();
                    var y    = msg.ReadSingle();
                    var hull = Entity.FindEntityByID(msg.ReadUInt16()) as Hull;
                    orderTargetPosition = new OrderTarget(new Vector2(x, y), hull, true);
                }

                if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
                {
                    DebugConsole.ThrowError($"Invalid order message from client \"{c.Name}\" - order index out of bounds ({orderIndex}, {orderOptionIndex}).");
                    if (NetIdUtils.IdMoreRecent(ID, c.LastSentChatMsgID))
                    {
                        c.LastSentChatMsgID = ID;
                    }
                    return;
                }

                Order  order       = Order.PrefabList[orderIndex];
                string orderOption = orderOptionIndex < 0 || orderOptionIndex >= order.Options.Length ? "" : order.Options[orderOptionIndex];
                orderMsg = new OrderChatMessage(order, orderOption, orderTargetPosition ?? orderTargetEntity as ISpatialEntity, orderTargetCharacter, c.Character);
                txt      = orderMsg.Text;
            }
            else
            {
                txt = msg.ReadString() ?? "";
            }

            if (!NetIdUtils.IdMoreRecent(ID, c.LastSentChatMsgID))
            {
                return;
            }

            c.LastSentChatMsgID = ID;

            if (txt.Length > MaxLength)
            {
                txt = txt.Substring(0, MaxLength);
            }

            c.LastSentChatMessages.Add(txt);
            if (c.LastSentChatMessages.Count > 10)
            {
                c.LastSentChatMessages.RemoveRange(0, c.LastSentChatMessages.Count - 10);
            }

            float similarity = 0.0f;

            for (int i = 0; i < c.LastSentChatMessages.Count; i++)
            {
                float closeFactor = 1.0f / (c.LastSentChatMessages.Count - i);

                if (string.IsNullOrEmpty(txt))
                {
                    similarity += closeFactor;
                }
                else
                {
                    int levenshteinDist = ToolBox.LevenshteinDistance(txt, c.LastSentChatMessages[i]);
                    similarity += Math.Max((txt.Length - levenshteinDist) / (float)txt.Length * closeFactor, 0.0f);
                }
            }
            //order/report messages can be sent a little faster than normal messages without triggering the spam filter
            if (orderMsg != null)
            {
                similarity *= 0.25f;
            }

            bool isOwner = GameMain.Server.OwnerConnection != null && c.Connection == GameMain.Server.OwnerConnection;

            if (similarity + c.ChatSpamSpeed > 5.0f && !isOwner)
            {
                GameMain.Server.KarmaManager.OnSpamFilterTriggered(c);

                c.ChatSpamCount++;
                if (c.ChatSpamCount > 3)
                {
                    //kick for spamming too much
                    GameMain.Server.KickClient(c, TextManager.Get("SpamFilterKicked"));
                }
                else
                {
                    ChatMessage denyMsg = Create("", TextManager.Get("SpamFilterBlocked"), ChatMessageType.Server, null);
                    c.ChatSpamTimer = 10.0f;
                    GameMain.Server.SendDirectChatMessage(denyMsg, c);
                }
                return;
            }

            c.ChatSpamSpeed += similarity + 0.5f;

            if (c.ChatSpamTimer > 0.0f && !isOwner)
            {
                ChatMessage denyMsg = Create("", TextManager.Get("SpamFilterBlocked"), ChatMessageType.Server, null);
                c.ChatSpamTimer = 10.0f;
                GameMain.Server.SendDirectChatMessage(denyMsg, c);
                return;
            }

            if (type == ChatMessageType.Order)
            {
                if (c.Character == null || c.Character.SpeechImpediment >= 100.0f || c.Character.IsDead)
                {
                    return;
                }
                if (orderMsg.Order.TargetAllCharacters)
                {
                    HumanAIController.ReportProblem(orderMsg.Sender, orderMsg.Order);
                }
                else if (orderTargetCharacter != null)
                {
                    var order = orderTargetPosition == null ?
                                new Order(orderMsg.Order.Prefab, orderTargetEntity, orderMsg.Order.Prefab?.GetTargetItemComponent(orderTargetEntity as Item), orderMsg.Sender) :
                                new Order(orderMsg.Order.Prefab, orderTargetPosition, orderMsg.Sender);
                    orderTargetCharacter.SetOrder(order, orderMsg.OrderOption, orderMsg.Sender);
                }
                GameMain.Server.SendOrderChatMessage(orderMsg);
            }
            else
            {
                GameMain.Server.SendChatMessage(txt, null, c);
            }
        }
Example #4
0
        public void Read(IReadMessage msg)
        {
            byte      queueId = msg.ReadByte();
            VoipQueue queue   = queues.Find(q => q.QueueID == queueId);

            if (queue == null)
            {
#if DEBUG
                DebugConsole.NewMessage("Couldn't find VoipQueue with id " + queueId.ToString() + "!", GUI.Style.Red);
#endif
                return;
            }

            Client client = gameClient.ConnectedClients.Find(c => c.VoipQueue == queue);
            if (queue.Read(msg, discardData: client.Muted || client.MutedLocally))
            {
                if (client.Muted || client.MutedLocally)
                {
                    return;
                }
                if (client.VoipSound == null)
                {
                    DebugConsole.Log("Recreating voipsound " + queueId);
                    client.VoipSound = new VoipSound(client.Name, GameMain.SoundManager, client.VoipQueue);
                }

                if (client.Character != null && !client.Character.IsDead && !client.Character.Removed && client.Character.SpeechImpediment <= 100.0f)
                {
                    WifiComponent radio       = null;
                    var           messageType = !client.VoipQueue.ForceLocal && ChatMessage.CanUseRadio(client.Character, out radio) ? ChatMessageType.Radio : ChatMessageType.Default;
                    client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);

                    client.VoipSound.UseRadioFilter = messageType == ChatMessageType.Radio;
                    if (client.VoipSound.UseRadioFilter)
                    {
                        client.VoipSound.SetRange(radio.Range * 0.8f, radio.Range);
                    }
                    else
                    {
                        client.VoipSound.SetRange(ChatMessage.SpeakRange * 0.4f, ChatMessage.SpeakRange);
                    }
                    if (!client.VoipSound.UseRadioFilter && Character.Controlled != null)
                    {
                        client.VoipSound.UseMuffleFilter = SoundPlayer.ShouldMuffleSound(Character.Controlled, client.Character.WorldPosition, ChatMessage.SpeakRange, client.Character.CurrentHull);
                    }
                }

                GameMain.NetLobbyScreen?.SetPlayerSpeaking(client);
                GameMain.GameSession?.CrewManager?.SetClientSpeaking(client);

                if ((client.VoipSound.CurrentAmplitude * client.VoipSound.Gain * GameMain.SoundManager.GetCategoryGainMultiplier("voip")) > 0.1f) //TODO: might need to tweak
                {
                    if (client.Character != null && !client.Character.Removed)
                    {
                        Vector3 clientPos       = new Vector3(client.Character.WorldPosition.X, client.Character.WorldPosition.Y, 0.0f);
                        Vector3 listenerPos     = GameMain.SoundManager.ListenerPosition;
                        float   attenuationDist = client.VoipSound.Near * 1.125f;
                        if (Vector3.DistanceSquared(clientPos, listenerPos) < attenuationDist * attenuationDist)
                        {
                            GameMain.SoundManager.VoipAttenuatedGain = 0.5f;
                        }
                    }
                    else
                    {
                        GameMain.SoundManager.VoipAttenuatedGain = 0.5f;
                    }
                }
            }
        }
Example #5
0
 public void AddChatMessage(string message, ChatMessageType type, string senderName = "", Client senderClient = null, Character senderCharacter = null, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None)
 {
     AddChatMessage(ChatMessage.Create(senderName, message, type, senderCharacter, senderClient, changeType: changeType));
 }