wifi wiring

This commit is contained in:
Evil Factory
2021-04-26 23:46:58 -03:00
parent b84d6a2872
commit 250163e1f5
2 changed files with 255 additions and 212 deletions
@@ -75,12 +75,28 @@ namespace Barotrauma
client.SpectatePos = pos; client.SpectatePos = pos;
} }
public static void SetRadioRange(Character character, float range)
{
if(character.Inventory == null) { return; }
foreach(Item item in character.Inventory.AllItems)
{
if(item == null) { continue; }
if(item.Name == "Headset")
{
item.GetComponent<Items.Components.WifiComponent>().Range = range;
}
}
}
} }
public class LuaGame public class LuaGame
{ {
LuaSetup env; LuaSetup env;
public bool allowWifiChat = false;
public bool overrideTraitors = false; public bool overrideTraitors = false;
public bool overrideRespawnSub = false; public bool overrideRespawnSub = false;
@@ -119,6 +135,11 @@ namespace Barotrauma
overrideRespawnSub = o; overrideRespawnSub = o;
} }
public void AllowWifiChat(bool o)
{
allowWifiChat = o;
}
public static void Log(string message, ServerLog.MessageType type) public static void Log(string message, ServerLog.MessageType type)
{ {
GameServer.Log(message, type); GameServer.Log(message, type);
@@ -8,195 +8,217 @@ using System.Xml.Linq;
namespace Barotrauma.Items.Components namespace Barotrauma.Items.Components
{ {
partial class WifiComponent : ItemComponent partial class WifiComponent : ItemComponent
{ {
private static readonly List<WifiComponent> list = new List<WifiComponent>(); private static readonly List<WifiComponent> list = new List<WifiComponent>();
const int ChannelMemorySize = 10; const int ChannelMemorySize = 10;
private float range; private float range;
private int channel; private int channel;
private float chatMsgCooldown;
private string prevSignal; private float chatMsgCooldown;
private int[] channelMemory = new int[ChannelMemorySize]; private string prevSignal;
[Serialize(CharacterTeamType.None, true, description: "WiFi components can only communicate with components that have the same Team ID.", alwaysUseInstanceValues: true)] private int[] channelMemory = new int[ChannelMemorySize];
public CharacterTeamType TeamID { get; set; }
[Editable, Serialize(20000.0f, false, description: "How close the recipient has to be to receive a signal from this WiFi component.", alwaysUseInstanceValues: true)] [Serialize(CharacterTeamType.None, true, description: "WiFi components can only communicate with components that have the same Team ID.", alwaysUseInstanceValues: true)]
public float Range public CharacterTeamType TeamID { get; set; }
{
get { return range; } [Editable, Serialize(20000.0f, false, description: "How close the recipient has to be to receive a signal from this WiFi component.", alwaysUseInstanceValues: true)]
set public float Range
{ {
range = Math.Max(value, 0.0f); get { return range; }
set
{
range = Math.Max(value, 0.0f);
#if CLIENT #if CLIENT
item.ResetCachedVisibleSize(); item.ResetCachedVisibleSize();
#endif #endif
} }
} }
[InGameEditable, Serialize(0, true, description: "WiFi components can only communicate with components that use the same channel.", alwaysUseInstanceValues: true)] [InGameEditable, Serialize(0, true, description: "WiFi components can only communicate with components that use the same channel.", alwaysUseInstanceValues: true)]
public int Channel public int Channel
{ {
get { return channel; } get { return channel; }
set set
{ {
channel = MathHelper.Clamp(value, 0, 10000); channel = MathHelper.Clamp(value, 0, 10000);
} }
} }
[Editable, Serialize(false, true, description: "Can the component communicate with wifi components in another team's submarine (e.g. enemy sub in Combat missions, respawn shuttle). Needs to be enabled on both the component transmitting the signal and the component receiving it.", alwaysUseInstanceValues: true)] [Editable, Serialize(false, true, description: "Can the component communicate with wifi components in another team's submarine (e.g. enemy sub in Combat missions, respawn shuttle). Needs to be enabled on both the component transmitting the signal and the component receiving it.", alwaysUseInstanceValues: true)]
public bool AllowCrossTeamCommunication public bool AllowCrossTeamCommunication
{ {
get; get;
set; set;
} }
[Editable, Serialize(false, false, description: "If enabled, any signals received from another chat-linked wifi component are displayed " + [Editable, Serialize(false, false, description: "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.", alwaysUseInstanceValues: true)] "as chat messages in the chatbox of the player holding the item.", alwaysUseInstanceValues: true)]
public bool LinkToChat public bool LinkToChat
{ {
get; get
set; {
} #if SERVER
return GameMain.Lua.game.allowWifiChat;
#endif
#if CLIENT
return LinkToChat;
#endif
}
set { }
}
[Editable, Serialize(1.0f, true, description: "How many seconds have to pass between signals for a message to be displayed in the chatbox. " + [Editable, Serialize(1.0f, true, description: "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 " + "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.")] "if there are chat-linked wifi components that transmit a continuous signal.")]
public float MinChatMessageInterval public float MinChatMessageInterval
{ {
get; get;
set; set;
} }
[Editable, Serialize(false, true, description: "If set to true, the component will only create chat messages when the received signal changes.")] [Editable, Serialize(false, true, description: "If set to true, the component will only create chat messages when the received signal changes.")]
public bool DiscardDuplicateChatMessages public bool DiscardDuplicateChatMessages
{ {
get; get;
set; set;
} }
public WifiComponent(Item item, XElement element) public WifiComponent(Item item, XElement element)
: base (item, element) : base(item, element)
{ {
list.Add(this); list.Add(this);
IsActive = true; IsActive = true;
channelMemory = element.GetAttributeIntArray("channelmemory", new int[ChannelMemorySize]); channelMemory = element.GetAttributeIntArray("channelmemory", new int[ChannelMemorySize]);
} }
public override void OnItemLoaded() public override void OnItemLoaded()
{ {
if (channelMemory.All(m => m == 0)) if (channelMemory.All(m => m == 0))
{ {
for (int i = 0; i < channelMemory.Length; i++) for (int i = 0; i < channelMemory.Length; i++)
{ {
channelMemory[i] = i; channelMemory[i] = i;
} }
} }
} }
public bool CanTransmit() public bool CanTransmit()
{ {
return HasRequiredContainedItems(user: null, addMessage: false); return HasRequiredContainedItems(user: null, addMessage: false);
} }
public IEnumerable<WifiComponent> GetReceiversInRange()
{
return list.Where(w => w != this && w.CanReceive(this));
}
public bool CanReceive(WifiComponent sender) public IEnumerable<WifiComponent> GetReceiversInRange()
{ {
if (sender == null || sender.channel != channel) { return false; } return list.Where(w => w != this && w.CanReceive(this));
}
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication) public bool CanReceive(WifiComponent sender)
{ {
return false; if (sender == null || sender.channel != channel) { return false; }
}
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; } if (sender.TeamID != TeamID && !AllowCrossTeamCommunication)
{
return false;
}
return HasRequiredContainedItems(user: null, addMessage: false); if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; }
}
public override void Update(float deltaTime, Camera cam) return HasRequiredContainedItems(user: null, addMessage: false);
{ }
chatMsgCooldown -= deltaTime;
if (chatMsgCooldown <= 0.0f)
{
IsActive = false;
}
}
public int GetChannelMemory(int index) public override void Update(float deltaTime, Camera cam)
{ {
if (index < 0 || index >= ChannelMemorySize) chatMsgCooldown -= deltaTime;
{ if (chatMsgCooldown <= 0.0f)
return 0; {
} IsActive = false;
return channelMemory[index]; }
} }
public void SetChannelMemory(int index, int value) public int GetChannelMemory(int index)
{ {
if (index < 0 || index >= ChannelMemorySize) if (index < 0 || index >= ChannelMemorySize)
{ {
return; return 0;
} }
channelMemory[index] = MathHelper.Clamp(value, 0, 10000); return channelMemory[index];
} }
public void TransmitSignal(Signal signal, bool sentFromChat) public void SetChannelMemory(int index, int value)
{ {
var senderComponent = signal.source?.GetComponent<WifiComponent>(); if (index < 0 || index >= ChannelMemorySize)
if (senderComponent != null && !CanReceive(senderComponent)) { return; } {
return;
}
channelMemory[index] = MathHelper.Clamp(value, 0, 10000);
}
bool chatMsgSent = false; public void TransmitSignal(Signal signal, bool sentFromChat)
{
var senderComponent = signal.source?.GetComponent<WifiComponent>();
if (senderComponent != null && !CanReceive(senderComponent)) { return; }
var receivers = GetReceiversInRange(); bool chatMsgSent = false;
foreach (WifiComponent wifiComp in receivers)
{
if (sentFromChat && !wifiComp.LinkToChat) { continue; }
//signal strength diminishes by distance var receivers = GetReceiversInRange();
float sentSignalStrength = signal.strength * foreach (WifiComponent wifiComp in receivers)
MathHelper.Clamp(1.0f - (Vector2.Distance(item.WorldPosition, wifiComp.item.WorldPosition) / wifiComp.range), 0.0f, 1.0f); {
Signal s = new Signal(signal.value, signal.stepsTaken, sender: signal.sender, source: signal.source, if (sentFromChat && !wifiComp.LinkToChat) { continue; }
power: 0.0f, strength: sentSignalStrength);
wifiComp.item.SendSignal(s, "signal_out");
if (signal.source != null)
{
foreach (Connection receiver in wifiComp.item.LastSentSignalRecipients)
{
if (!signal.source.LastSentSignalRecipients.Contains(receiver))
{
signal.source.LastSentSignalRecipients.Add(receiver);
}
}
}
if (DiscardDuplicateChatMessages && signal.value == prevSignal) { continue; } //signal strength diminishes by distance
float sentSignalStrength = signal.strength *
MathHelper.Clamp(1.0f - (Vector2.Distance(item.WorldPosition, wifiComp.item.WorldPosition) / wifiComp.range), 0.0f, 1.0f);
//create a chat message if (sentFromChat && wifiComp.LinkToChat)
if (LinkToChat && wifiComp.LinkToChat && chatMsgCooldown <= 0.0f && !sentFromChat) {
{
if (wifiComp.item.ParentInventory != null && //Signal s = new Signal(signal.value, signal.stepsTaken, sender: null, source: null, power: 0.0f, strength: sentSignalStrength);
wifiComp.item.ParentInventory.Owner != null)
{ signal.source = null;
string chatMsg = signal.value;
if (senderComponent != null) wifiComp.item.SendSignal(signal, "signal_out");
{
chatMsg = ChatMessage.ApplyDistanceEffect(chatMsg, 1.0f - sentSignalStrength); }
} else
if (chatMsg.Length > ChatMessage.MaxLength) { chatMsg = chatMsg.Substring(0, ChatMessage.MaxLength); } {
if (string.IsNullOrEmpty(chatMsg)) { continue; } Signal s = new Signal(signal.value, signal.stepsTaken, sender: signal.sender, source: signal.source, power: 0.0f, strength: sentSignalStrength);
wifiComp.item.SendSignal(s, "signal_out");
}
if (signal.source != null)
{
foreach (Connection receiver in wifiComp.item.LastSentSignalRecipients)
{
if (!signal.source.LastSentSignalRecipients.Contains(receiver))
{
signal.source.LastSentSignalRecipients.Add(receiver);
}
}
}
if (DiscardDuplicateChatMessages && signal.value == prevSignal) { continue; }
//create a chat message
if (LinkToChat && wifiComp.LinkToChat && chatMsgCooldown <= 0.0f && !sentFromChat)
{
if (wifiComp.item.ParentInventory != null &&
wifiComp.item.ParentInventory.Owner != null)
{
string chatMsg = signal.value;
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 CLIENT
if (wifiComp.item.ParentInventory.Owner == Character.Controlled) if (wifiComp.item.ParentInventory.Owner == Character.Controlled)
@@ -207,64 +229,64 @@ namespace Barotrauma.Items.Components
} }
} }
#elif SERVER #elif SERVER
if (GameMain.Server != null) if (GameMain.Server != null)
{ {
Client recipientClient = GameMain.Server.ConnectedClients.Find(c => c.Character == wifiComp.item.ParentInventory.Owner); Client recipientClient = GameMain.Server.ConnectedClients.Find(c => c.Character == wifiComp.item.ParentInventory.Owner);
if (recipientClient != null) if (recipientClient != null)
{ {
GameMain.Server.SendDirectChatMessage( GameMain.Server.SendDirectChatMessage(
ChatMessage.Create(signal.source?.Name ?? "", chatMsg, ChatMessageType.Radio, null), recipientClient); ChatMessage.Create(signal.source?.Name ?? "", chatMsg, ChatMessageType.Radio, null), recipientClient);
} }
} }
#endif #endif
chatMsgSent = true; chatMsgSent = true;
} }
} }
} }
if (chatMsgSent) if (chatMsgSent)
{ {
chatMsgCooldown = MinChatMessageInterval; chatMsgCooldown = MinChatMessageInterval;
IsActive = true; IsActive = true;
} }
prevSignal = signal.value; prevSignal = signal.value;
} }
public override void ReceiveSignal(Signal signal, Connection connection)
{
if (connection == null) { return; }
switch (connection.Name) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
case "signal_in": if (connection == null) { return; }
TransmitSignal(signal, false);
break;
case "set_channel":
if (int.TryParse(signal.value, out int newChannel))
{
Channel = newChannel;
}
break;
case "set_range":
if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newRange))
{
Range = newRange;
}
break;
}
}
protected override void RemoveComponentSpecific() switch (connection.Name)
{ {
base.RemoveComponentSpecific(); case "signal_in":
list.Remove(this); TransmitSignal(signal, false);
} break;
case "set_channel":
if (int.TryParse(signal.value, out int newChannel))
{
Channel = newChannel;
}
break;
case "set_range":
if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newRange))
{
Range = newRange;
}
break;
}
}
public override XElement Save(XElement parentElement) protected override void RemoveComponentSpecific()
{ {
var element = base.Save(parentElement); base.RemoveComponentSpecific();
element.Add(new XAttribute("channelmemory", string.Join(',', channelMemory))); list.Remove(this);
return element; }
}
} public override XElement Save(XElement parentElement)
{
var element = base.Save(parentElement);
element.Add(new XAttribute("channelmemory", string.Join(',', channelMemory)));
return element;
}
}
} }