using Barotrauma.Networking; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Xml.Linq; namespace Barotrauma.Items.Components { partial class WifiComponent : ItemComponent { private static List list = new List(); private float range; private int channel; private float chatMsgCooldown; private string prevSignal; public Character.TeamType TeamID; [Serialize(20000.0f, false)] public float Range { get { return range; } set { range = Math.Max(value, 0.0f); } } [InGameEditable, Serialize(1, true)] public int Channel { get { return channel; } set { channel = MathHelper.Clamp(value, 0, 10000); } } [Editable(ToolTip = "If enabled, any signals received from another chat-linked wifi component are displayed "+ "as chat messages in the chatbox of the player holding the item."), Serialize(false, false)] public bool LinkToChat { get; set; } [Editable(ToolTip = "How many seconds have to pass between signals for a message to be displayed in the chatbox. "+ "Setting this to a very low value is not recommended, because it may cause an excessive amount of chat messages to be created "+ "if there are chat-linked wifi components that transmit a continuous signal."), Serialize(1.0f, true)] public float MinChatMessageInterval { get; set; } [Editable(ToolTip = "If set to true, the component will only create chat messages when the received signal changes."), Serialize(false, true)] public bool DiscardDuplicateChatMessages { get; set; } public WifiComponent(Item item, XElement element) : base (item, element) { list.Add(this); IsActive = true; } public bool CanTransmit() { return HasRequiredContainedItems(true); } private List GetReceiversInRange() { return list.FindAll(w => w != this && w.CanReceive(this)); } public bool CanReceive(WifiComponent sender) { if (sender == null || sender.channel != channel || sender.TeamID != TeamID) return false; if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) return false; return HasRequiredContainedItems(false); } public override void Update(float deltaTime, Camera cam) { chatMsgCooldown -= deltaTime; } public void TransmitSignal(int stepsTaken, string signal, Item source, Character sender, bool sendToChat, float signalStrength = 1.0f) { var senderComponent = source?.GetComponent(); if (senderComponent != null && !CanReceive(senderComponent)) return; bool chatMsgSent = false; var receivers = GetReceiversInRange(); foreach (WifiComponent wifiComp in receivers) { //signal strength diminishes by distance float sentSignalStrength = signalStrength * MathHelper.Clamp(1.0f - (Vector2.Distance(item.WorldPosition, wifiComp.item.WorldPosition) / wifiComp.range), 0.0f, 1.0f); wifiComp.item.SendSignal(stepsTaken, signal, "signal_out", sender, 0, source, sentSignalStrength); if (source != null) { foreach (Item receiverItem in wifiComp.item.LastSentSignalRecipients) { if (!source.LastSentSignalRecipients.Contains(receiverItem)) { source.LastSentSignalRecipients.Add(receiverItem); } } } if (DiscardDuplicateChatMessages && signal == prevSignal) continue; if (LinkToChat && wifiComp.LinkToChat && chatMsgCooldown <= 0.0f && sendToChat) { if (wifiComp.item.ParentInventory != null && wifiComp.item.ParentInventory.Owner != null && GameMain.NetworkMember != null) { string chatMsg = signal; if (senderComponent != null) { chatMsg = ChatMessage.ApplyDistanceEffect(chatMsg, 1.0f - sentSignalStrength); } if (chatMsg.Length > ChatMessage.MaxLength) chatMsg = chatMsg.Substring(0, ChatMessage.MaxLength); if (string.IsNullOrEmpty(chatMsg)) continue; #if CLIENT if (wifiComp.item.ParentInventory.Owner == Character.Controlled) { if (GameMain.Client == null) GameMain.NetworkMember.AddChatMessage(signal, ChatMessageType.Radio, source == null ? "" : source.Name); } #endif #if SERVER if (GameMain.Server != null) { Client recipientClient = GameMain.Server.ConnectedClients.Find(c => c.Character == wifiComp.item.ParentInventory.Owner); if (recipientClient != null) { GameMain.Server.SendDirectChatMessage( ChatMessage.Create(source == null ? "" : source.Name, chatMsg, ChatMessageType.Radio, null), recipientClient); } } #endif chatMsgSent = true; } } } if (chatMsgSent) chatMsgCooldown = MinChatMessageInterval; prevSignal = signal; } public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) { if (connection == null || connection.Name != "signal_in") return; TransmitSignal(stepsTaken, signal, source, sender, true, signalStrength); } protected override void RemoveComponentSpecific() { base.RemoveComponentSpecific(); list.Remove(this); } } }