Server LuaCsForBarotrauma
VoipServer.cs
2 using Microsoft.Xna.Framework;
3 using System;
4 using System.Collections.Generic;
5 
6 namespace Barotrauma.Networking
7 {
8  class VoipServer
9  {
10  private readonly ServerPeer netServer;
11  private readonly List<VoipQueue> queues;
12  private readonly Dictionary<VoipQueue, DateTime> lastSendTime;
13 
14  public VoipServer(ServerPeer server)
15  {
16  netServer = server;
17  queues = new List<VoipQueue>();
18  lastSendTime = new Dictionary<VoipQueue, DateTime>();
19  }
20 
21  public void RegisterQueue(VoipQueue queue)
22  {
23  if (!queues.Contains(queue)) queues.Add(queue);
24  }
25 
26  public void UnregisterQueue(VoipQueue queue)
27  {
28  if (queues.Contains(queue)) queues.Remove(queue);
29  }
30 
31  public void SendToClients(List<Client> clients)
32  {
33  foreach (VoipQueue queue in queues)
34  {
35  if (queue.LastReadTime < DateTime.Now - VoipConfig.SEND_INTERVAL) { continue; }
36 
37  if (lastSendTime.ContainsKey(queue))
38  {
39  if ((lastSendTime[queue] + VoipConfig.SEND_INTERVAL) > DateTime.Now) { continue; }
40  lastSendTime[queue] = DateTime.Now;
41  }
42  else
43  {
44  lastSendTime.Add(queue, DateTime.Now);
45  }
46 
47  Client sender = clients.Find(c => c.VoipQueue == queue);
48  if (sender == null) { return; }
49 
50  foreach (Client recipient in clients)
51  {
52  if (recipient == sender) { continue; }
53 
54  if (!CanReceive(sender, recipient, out float distanceFactor)) { continue; }
55 
56  IWriteMessage msg = new WriteOnlyMessage();
57 
58  msg.WriteByte((byte)ServerPacketHeader.VOICE);
59  msg.WriteByte((byte)queue.QueueID);
60  msg.WriteRangedSingle(distanceFactor, 0.0f, 1.0f, 8);
61  queue.Write(msg);
62 
63  netServer.Send(msg, recipient.Connection, DeliveryMethod.Unreliable);
64  }
65  }
66  }
67 
68  private static bool CanReceive(Client sender, Client recipient, out float distanceFactor)
69  {
71  {
72  distanceFactor = 0.0f;
73  return true;
74  }
75 
76  distanceFactor = 0.0f;
77 
78  //no-one can hear muted players
79  if (sender.Muted) { return false; }
80 
81  bool recipientSpectating = recipient.Character == null || recipient.Character.IsDead;
82  bool senderSpectating = sender.Character == null || sender.Character.IsDead;
83 
84  //non-spectators cannot hear spectators, and spectators can always hear spectators
85  if (senderSpectating)
86  {
87  return recipientSpectating;
88  }
89 
90  //sender can't speak
91  if (sender.Character != null && sender.Character.SpeechImpediment >= 100.0f) { return false; }
92 
93  //check if the message can be sent via radio
94  WifiComponent recipientRadio = null;
95  if (!sender.VoipQueue.ForceLocal &&
96  ChatMessage.CanUseRadio(sender.Character, out WifiComponent senderRadio) &&
97  (recipientSpectating || ChatMessage.CanUseRadio(recipient.Character, out recipientRadio)))
98  {
99  var canUse = GameMain.LuaCs.Hook.Call<bool?>("canUseVoiceRadio", new object[] { sender, recipient });
100 
101  if (canUse != null)
102  {
103  return canUse.Value;
104  }
105 
106  if (recipientSpectating)
107  {
108  if (recipient.SpectatePos == null) { return true; }
109  distanceFactor = MathHelper.Clamp(Vector2.Distance(sender.Character.WorldPosition, recipient.SpectatePos.Value) / senderRadio.Range, 0.0f, 1.0f);
110  return distanceFactor < 1.0f;
111  }
112  else if (recipientRadio != null && recipientRadio.CanReceive(senderRadio))
113  {
114  distanceFactor = MathHelper.Clamp(Vector2.Distance(sender.Character.WorldPosition, recipient.Character.WorldPosition) / senderRadio.Range, 0.0f, 1.0f);
115  return true;
116  }
117  }
118 
119  float range = GameMain.LuaCs.Hook.Call<float?>("changeLocalVoiceRange", sender, recipient) ?? 1.0f;
120 
121  if (recipientSpectating)
122  {
123  if (recipient.SpectatePos == null) { return true; }
124  distanceFactor = MathHelper.Clamp(Vector2.Distance(sender.Character.WorldPosition, recipient.SpectatePos.Value) / ChatMessage.SpeakRangeVOIP, 0.0f, 1.0f);
125  return distanceFactor < 1.0f;
126  }
127  else
128  {
129  //otherwise do a distance check
130  float garbleAmount = ChatMessage.GetGarbleAmount(recipient.Character, sender.Character, ChatMessage.SpeakRangeVOIP);
131  distanceFactor = garbleAmount;
132  return garbleAmount < range;
133  }
134  }
135 
136  public static void Read(IReadMessage inc, Client connectedClient)
137  {
138  var queue = connectedClient.VoipQueue;
139  if (queue.Read(inc, discardData: false))
140  {
141  connectedClient.VoipServerDecoder.OnNewVoiceReceived();
142  }
143 
144 #if DEBUG
145  var msg = new WriteOnlyMessage().WithHeader(ServerPacketHeader.VOICE_AMPLITUDE_DEBUG);
146  msg.WriteRangedSingle(connectedClient.VoipServerDecoder.Amplitude, min: 0, max: 1, bitCount: 8);
147 
148  GameMain.Server?.ServerPeer?.Send(msg, connectedClient.Connection, DeliveryMethod.Unreliable);
149 #endif
150  }
151  }
152 }
Character(CharacterPrefab prefab, Vector2 position, string seed, CharacterInfo characterInfo=null, ushort id=Entity.NullEntityID, bool isRemotePlayer=false, RagdollParams ragdollParams=null, bool spawnInitialItems=true)
virtual Vector2 WorldPosition
Definition: Entity.cs:49
static GameScreen GameScreen
Definition: GameMain.cs:56
static GameServer Server
Definition: GameMain.cs:39
const float SpeakRangeVOIP
This is shorter than the text chat speak range, because the voice chat is still intelligible (just qu...
static float GetGarbleAmount(Entity listener, Entity sender, float range, float obstructionMultiplier=2.0f)
How much messages sent by sender should get garbled. Takes the distance between the entities and opt...
static bool CanUseRadio(Character sender, bool ignoreJamming=false)
virtual void Write(IWriteMessage msg)
Definition: VoipQueue.cs:118
void RegisterQueue(VoipQueue queue)
Definition: VoipServer.cs:21
static void Read(IReadMessage inc, Client connectedClient)
Definition: VoipServer.cs:136
VoipServer(ServerPeer server)
Definition: VoipServer.cs:14
void UnregisterQueue(VoipQueue queue)
Definition: VoipServer.cs:26
void SendToClients(List< Client > clients)
Definition: VoipServer.cs:31
static Screen Selected
Definition: Screen.cs:5
void WriteRangedSingle(Single val, Single min, Single max, int bitCount)