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); } }
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); } }
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; } } } }
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)); }