(f417b026f) Fetched: Changes for playing video tutorial from local branch
This commit is contained in:
@@ -4,6 +4,11 @@ namespace Barotrauma
|
||||
{
|
||||
partial class CharacterInfo
|
||||
{
|
||||
partial void SpawnInventoryItemProjSpecific(Item item)
|
||||
{
|
||||
Entity.Spawner.CreateNetworkEvent(item, false);
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg)
|
||||
{
|
||||
msg.Write(ID);
|
||||
|
||||
@@ -81,12 +81,11 @@ namespace Barotrauma
|
||||
//dequeue messages
|
||||
lock (queuedMessages)
|
||||
{
|
||||
if (queuedMessages.Count > 0)
|
||||
if (queuedMessages.Count>0)
|
||||
{
|
||||
int inputLines = Math.Max((int)Math.Ceiling(input.Length / (float)Console.WindowWidth), 1);
|
||||
Console.CursorLeft = 0;
|
||||
Console.Write(new string(' ', consoleWidth));
|
||||
Console.CursorTop -= inputLines; Console.CursorLeft = 0;
|
||||
Console.CursorTop--; Console.CursorLeft = 0;
|
||||
while (queuedMessages.Count > 0)
|
||||
{
|
||||
ColoredText msg = queuedMessages.Dequeue();
|
||||
@@ -178,11 +177,11 @@ namespace Barotrauma
|
||||
|
||||
private static void RewriteInputToCommandLine(string input)
|
||||
{
|
||||
int consoleWidth = Math.Max(Console.WindowWidth, 5);
|
||||
int inputLines = Math.Max((int)Math.Ceiling(input.Length / (float)consoleWidth), 1);
|
||||
int cursorLine = Math.Max((int)Math.Ceiling((input.Length + 1) / (float)consoleWidth), 1);
|
||||
|
||||
Console.WriteLine(""); Console.CursorTop -= inputLines;
|
||||
Console.WriteLine(""); Console.CursorTop--;
|
||||
int consoleWidth = Console.WindowWidth;
|
||||
if (consoleWidth < 5) consoleWidth = 5;
|
||||
int consoleHeight = Console.WindowHeight;
|
||||
if (consoleHeight < 5) consoleHeight = 5;
|
||||
|
||||
string ln = input.Length > 0 ? AutoComplete(input, 0) : "";
|
||||
ln += new string(' ', consoleWidth - (ln.Length % consoleWidth));
|
||||
@@ -191,9 +190,9 @@ namespace Barotrauma
|
||||
Console.Write(ln);
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.CursorLeft = 0;
|
||||
Console.CursorTop -= cursorLine;
|
||||
Console.CursorTop--;
|
||||
Console.Write(input);
|
||||
Console.CursorLeft = input.Length % Console.WindowWidth;
|
||||
Console.CursorLeft = input.Length;
|
||||
}
|
||||
|
||||
private static void AssignOnClientRequestExecute(string names, Action<Client, Vector2, string[]> onClientRequestExecute)
|
||||
@@ -1555,9 +1554,9 @@ namespace Barotrauma
|
||||
}));
|
||||
|
||||
#if DEBUG
|
||||
commands.Add(new Command("spamevents", "A debug command that creates a ton of entity events.", (string[] args) =>
|
||||
commands.Add(new Command("spamevents", "A debug command that immediately creates entity events for all items, characters and structures.", (string[] args) =>
|
||||
{
|
||||
/*foreach (Item item in Item.ItemList)
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
foreach (ItemComponent component in item.Components)
|
||||
{
|
||||
@@ -1574,18 +1573,16 @@ namespace Barotrauma
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status });
|
||||
}*/
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(hull);
|
||||
}
|
||||
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(wall);
|
||||
}
|
||||
}
|
||||
}));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace Barotrauma
|
||||
{
|
||||
private List<CharacterCampaignData> characterData = new List<CharacterCampaignData>();
|
||||
|
||||
public static void StartNewCampaign(string savePath, string subPath, string seed)
|
||||
public static void StartNewCampaign(string savePath, string subName, string seed)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(savePath)) return;
|
||||
|
||||
GameMain.GameSession = new GameSession(new Submarine(subPath, ""), savePath,
|
||||
GameMain.GameSession = new GameSession(new Submarine(subName, ""), savePath,
|
||||
GameModePreset.List.Find(g => g.Identifier == "multiplayercampaign"));
|
||||
var campaign = ((MultiPlayerCampaign)GameMain.GameSession.GameMode);
|
||||
campaign.GenerateMap(seed);
|
||||
@@ -72,27 +72,6 @@ namespace Barotrauma
|
||||
});
|
||||
}
|
||||
|
||||
public bool AllowedToEndRound(Character interactor)
|
||||
{
|
||||
if (interactor == null || Level.Loaded?.StartOutpost == null || Level.Loaded?.EndOutpost == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (interactor.Submarine == Level.Loaded.StartOutpost &&
|
||||
interactor.CanInteractWith(startWatchman))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (interactor.Submarine == Level.Loaded.EndOutpost &&
|
||||
interactor.CanInteractWith(endWatchman))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void WatchmanInteract(Character watchman, Character interactor)
|
||||
{
|
||||
if ((watchman.Submarine == Level.Loaded.StartOutpost && !Submarine.MainSub.AtStartPosition) ||
|
||||
@@ -106,7 +85,8 @@ namespace Barotrauma
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Character == interactor);
|
||||
hasPermissions = client != null;
|
||||
hasPermissions = client != null &&
|
||||
(client.HasPermission(ClientPermissions.ManageRound) || client.HasPermission(ClientPermissions.ManageCampaign));
|
||||
CreateDialog(new List<Character> { watchman }, hasPermissions ? "WatchmanInteract" : "WatchmanInteractNotAllowed", 1.0f);
|
||||
}
|
||||
}
|
||||
@@ -251,7 +231,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
lastSaveID++;
|
||||
DebugConsole.Log("Campaign saved, save ID " + lastSaveID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -10,16 +14,5 @@ namespace Barotrauma.Items.Components
|
||||
//let the clients know the initial deterioration delay
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
if (c.Character == null) return;
|
||||
StartRepairing(c.Character);
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(deteriorationTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,14 +335,6 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.Server == null) return;
|
||||
|
||||
if (!ItemList.Contains(this))
|
||||
{
|
||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = components.IndexOf(ic);
|
||||
if (index == -1) return;
|
||||
|
||||
|
||||
@@ -20,16 +20,6 @@ namespace Barotrauma
|
||||
partial void UpdateProjSpecific(float deltaTime, Camera cam)
|
||||
{
|
||||
if (IdFreed) { return; }
|
||||
|
||||
//don't create updates if all clients are very far from the hull
|
||||
float hullUpdateDistanceSqr = NetConfig.HullUpdateDistance * NetConfig.HullUpdateDistance;
|
||||
if (!GameMain.Server.ConnectedClients.Any(c =>
|
||||
c.Character != null &&
|
||||
Vector2.DistanceSquared(c.Character.WorldPosition, WorldPosition) < hullUpdateDistanceSqr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//update client hulls if the amount of water has changed by >10%
|
||||
//or if oxygen percentage has changed by 5%
|
||||
if (Math.Abs(lastSentVolume - waterVolume) > Volume * 0.1f ||
|
||||
@@ -41,8 +31,8 @@ namespace Barotrauma
|
||||
GameMain.NetworkMember.CreateEntityEvent(this);
|
||||
lastSentVolume = waterVolume;
|
||||
lastSentOxygen = OxygenPercentage;
|
||||
sendUpdateTimer = NetConfig.HullUpdateInterval;
|
||||
}
|
||||
sendUpdateTimer = NetworkUpdateInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
//when was a specific entity event last sent to the client
|
||||
// key = event id, value = NetTime.Now when sending
|
||||
public readonly Dictionary<UInt16, double> EntityEventLastSent = new Dictionary<UInt16, double>();
|
||||
public readonly Dictionary<UInt16, float> EntityEventLastSent = new Dictionary<UInt16, float>();
|
||||
|
||||
//when was a position update for a given entity last sent to the client
|
||||
// key = entity id, value = NetTime.Now when sending
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace Barotrauma.Networking
|
||||
transfer.WaitTimer -= deltaTime;
|
||||
if (transfer.WaitTimer > 0.0f) continue;
|
||||
|
||||
if (!transfer.Connection.CanSendImmediately(NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel)) continue;
|
||||
if (!transfer.Connection.CanSendImmediately(NetDeliveryMethod.ReliableOrdered, 1)) continue;
|
||||
|
||||
transfer.WaitTimer = 0.05f;// transfer.Connection.AverageRoundtripTime;
|
||||
|
||||
@@ -202,6 +202,15 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
message = peer.CreateMessage();
|
||||
message.Write((byte)ServerPacketHeader.FILE_TRANSFER);
|
||||
message.Write((byte)FileTransferMessageType.Initiate);
|
||||
message.Write((byte)transfer.FileType);
|
||||
message.Write((ushort)chunkLen);
|
||||
message.Write((ulong)transfer.Data.Length);
|
||||
message.Write(transfer.FileName);
|
||||
GameMain.Server.CompressOutgoingMessage(message);
|
||||
transfer.Connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel);
|
||||
|
||||
transfer.Status = FileTransferStatus.Sending;
|
||||
|
||||
//if the recipient is the owner of the server (= a client running the server from the main exe)
|
||||
//we don't need to send anything, the client can just read the file directly
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Text;
|
||||
using System.IO.Compression;
|
||||
using System.IO;
|
||||
using Barotrauma.Steam;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -44,7 +43,6 @@ namespace Barotrauma.Networking
|
||||
private IRestResponse masterServerResponse;
|
||||
|
||||
private bool autoRestartTimerRunning;
|
||||
private float endRoundTimer;
|
||||
|
||||
public VoipServer VoipServer
|
||||
{
|
||||
@@ -407,38 +405,20 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (isCrewDead && respawnManager == null)
|
||||
{
|
||||
if (endRoundTimer <= 0.0f)
|
||||
{
|
||||
SendChatMessage(TextManager.Get("CrewDeadNoRespawns").Replace("[time]", "60"), ChatMessageType.Server);
|
||||
}
|
||||
endRoundTimer += deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
endRoundTimer = 0.0f;
|
||||
}
|
||||
|
||||
//restart if all characters are dead or submarine is at the end of the level
|
||||
if ((serverSettings.AutoRestart && isCrewDead)
|
||||
||
|
||||
(serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
|
||||
||
|
||||
(isCrewDead && respawnManager == null && endRoundTimer >= 60.0f))
|
||||
(serverSettings.EndRoundAtLevelEnd && subAtLevelEnd))
|
||||
{
|
||||
if (serverSettings.AutoRestart && isCrewDead)
|
||||
{
|
||||
Log("Ending round (entire crew dead)", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
else if (serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
|
||||
else
|
||||
{
|
||||
Log("Ending round (submarine reached the end of the level)", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Ending round (no living players left and respawning is not enabled during this round)", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
|
||||
EndGame();
|
||||
return;
|
||||
}
|
||||
@@ -717,24 +697,13 @@ namespace Barotrauma.Networking
|
||||
string savePath = inc.ReadString();
|
||||
string seed = inc.ReadString();
|
||||
string subName = inc.ReadString();
|
||||
string subHash = inc.ReadString();
|
||||
|
||||
var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
|
||||
|
||||
if (matchingSub == null)
|
||||
{
|
||||
SendDirectChatMessage(
|
||||
TextManager.Get("CampaignStartFailedSubNotFound").Replace("[subname]", subName),
|
||||
connectedClient, ChatMessageType.MessageBox);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode)) MultiPlayerCampaign.StartNewCampaign(savePath, matchingSub.FilePath, seed);
|
||||
}
|
||||
}
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode)) MultiPlayerCampaign.StartNewCampaign(savePath, subName, seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
string saveName = inc.ReadString();
|
||||
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode)) MultiPlayerCampaign.LoadCampaign(saveName);
|
||||
}
|
||||
break;
|
||||
@@ -765,64 +734,6 @@ namespace Barotrauma.Networking
|
||||
fileSender.ReadFileRequest(inc, connectedClient);
|
||||
}
|
||||
break;
|
||||
case ClientPacketHeader.ERROR:
|
||||
HandleClientError(inc, connectedClient);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleClientError(NetIncomingMessage inc, Client c)
|
||||
{
|
||||
string errorStr = "Unhandled error report";
|
||||
|
||||
ClientNetError error = (ClientNetError)inc.ReadByte();
|
||||
int levelEqualityCheckVal = inc.ReadInt32();
|
||||
switch (error)
|
||||
{
|
||||
case ClientNetError.MISSING_EVENT:
|
||||
UInt16 expectedID = inc.ReadUInt16();
|
||||
UInt16 receivedID = inc.ReadUInt16();
|
||||
errorStr = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString();
|
||||
break;
|
||||
case ClientNetError.MISSING_ENTITY:
|
||||
UInt16 eventID = inc.ReadUInt16();
|
||||
UInt16 entityID = inc.ReadUInt16();
|
||||
Entity entity = Entity.FindEntityByID(entityID);
|
||||
if (entity == null)
|
||||
{
|
||||
errorStr = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else if (entity is Character character)
|
||||
{
|
||||
errorStr = "Missing character " + character.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else if (entity is Item item)
|
||||
{
|
||||
errorStr = "Missing item " + item.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else
|
||||
{
|
||||
errorStr = "Missing entity " + entity.ToString() + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (Level.Loaded != null && levelEqualityCheckVal != Level.Loaded.EqualityCheckVal)
|
||||
{
|
||||
errorStr += " Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
||||
}
|
||||
|
||||
Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.HandleClientError:LevelsDontMatch" + error, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorStr);
|
||||
|
||||
if (c.Connection == OwnerConnection)
|
||||
{
|
||||
SendDirectChatMessage(errorStr, c, ChatMessageType.MessageBox);
|
||||
EndGame();
|
||||
}
|
||||
else
|
||||
{
|
||||
KickClient(c, errorStr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,8 +791,8 @@ namespace Barotrauma.Networking
|
||||
//(the server started a new campaign and the client isn't aware of it yet?)
|
||||
if (campaign.CampaignID != campaignID)
|
||||
{
|
||||
c.LastRecvCampaignSave = (ushort)(campaign.LastSaveID - 1);
|
||||
c.LastRecvCampaignUpdate = (ushort)(campaign.LastUpdateID - 1);
|
||||
c.LastRecvCampaignSave = 0;
|
||||
c.LastRecvCampaignUpdate = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1035,17 +946,7 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
//clients are allowed to end the round by talking with the watchman in multiplayer
|
||||
//campaign even if they don't have the special permission
|
||||
if (command == ClientPermissions.ManageRound && inc.PeekBoolean() &&
|
||||
GameMain.GameSession?.GameMode is MultiPlayerCampaign mpCampaign)
|
||||
{
|
||||
if (!mpCampaign.AllowedToEndRound(sender.Character) && !sender.HasPermission(command))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!sender.HasPermission(command))
|
||||
if (!sender.HasPermission(command))
|
||||
{
|
||||
Log("Client \"" + sender.Name + "\" sent a server command \"" + command + "\". Permission denied.", ServerLog.MessageType.ServerMessage);
|
||||
return;
|
||||
@@ -1126,22 +1027,9 @@ namespace Barotrauma.Networking
|
||||
UInt16 modeIndex = inc.ReadUInt16();
|
||||
if (GameMain.NetLobbyScreen.GameModes[modeIndex].Identifier.ToLowerInvariant() == "multiplayercampaign")
|
||||
{
|
||||
string[] saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
|
||||
for (int i = 0; i < saveFiles.Length; i++)
|
||||
{
|
||||
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFiles[i]);
|
||||
if (doc?.Root != null)
|
||||
{
|
||||
saveFiles[i] =
|
||||
string.Join(";",
|
||||
saveFiles[i].Replace(';', ' '),
|
||||
doc.Root.GetAttributeString("submarine", ""),
|
||||
doc.Root.GetAttributeString("savetime", ""));
|
||||
}
|
||||
}
|
||||
|
||||
NetOutgoingMessage msg = server.CreateMessage();
|
||||
msg.Write((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO);
|
||||
string[] saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
|
||||
msg.Write((UInt16)saveFiles.Count());
|
||||
foreach (string saveFile in saveFiles)
|
||||
{
|
||||
@@ -1226,7 +1114,6 @@ namespace Barotrauma.Networking
|
||||
ClientWriteLobby(c);
|
||||
|
||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign &&
|
||||
GameMain.NetLobbyScreen.SelectedMode == campaign.Preset &&
|
||||
NetIdUtils.IdMoreRecent(campaign.LastSaveID, c.LastRecvCampaignSave))
|
||||
{
|
||||
//already sent an up-to-date campaign save
|
||||
@@ -1361,6 +1248,10 @@ namespace Barotrauma.Networking
|
||||
WriteClientList(c, outmsg);
|
||||
clientListBytes = outmsg.LengthBytes - clientListBytes;
|
||||
|
||||
int eventManagerBytes = outmsg.LengthBytes;
|
||||
entityEventManager.Write(c, outmsg, out List<NetEntityEvent> sentEvents);
|
||||
eventManagerBytes = outmsg.LengthBytes - eventManagerBytes;
|
||||
|
||||
int chatMessageBytes = outmsg.LengthBytes;
|
||||
WriteChatMessages(outmsg, c);
|
||||
chatMessageBytes = outmsg.LengthBytes - chatMessageBytes;
|
||||
@@ -1409,55 +1300,25 @@ namespace Barotrauma.Networking
|
||||
errorMsg +=
|
||||
" Client list size: " + clientListBytes + " bytes\n" +
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Event size: " + eventManagerBytes + " bytes\n" +
|
||||
" Position update size: " + positionUpdateBytes + " bytes\n\n";
|
||||
|
||||
if (sentEvents != null && sentEvents.Count > 0)
|
||||
{
|
||||
errorMsg += "Sent events: \n";
|
||||
foreach (var entityEvent in sentEvents)
|
||||
{
|
||||
errorMsg += " - " + (entityEvent.Entity?.ToString() ?? "null") + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
CompressOutgoingMessage(outmsg);
|
||||
|
||||
server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
for (int i = 0; i < NetConfig.MaxEventPacketsPerUpdate; i++)
|
||||
{
|
||||
outmsg = server.CreateMessage();
|
||||
outmsg.Write((byte)ServerPacketHeader.UPDATE_INGAME);
|
||||
outmsg.Write((float)NetTime.Now);
|
||||
|
||||
int eventManagerBytes = outmsg.LengthBytes;
|
||||
entityEventManager.Write(c, outmsg, out List<NetEntityEvent> sentEvents);
|
||||
eventManagerBytes = outmsg.LengthBytes - eventManagerBytes;
|
||||
|
||||
if (sentEvents.Count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
|
||||
if (outmsg.LengthBytes > NetPeerConfiguration.MaximumTransmissionUnit)
|
||||
{
|
||||
string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + NetPeerConfiguration.MaximumTransmissionUnit + ")\n";
|
||||
errorMsg +=
|
||||
" Event size: " + eventManagerBytes + " bytes\n";
|
||||
|
||||
if (sentEvents != null && sentEvents.Count > 0)
|
||||
{
|
||||
errorMsg += "Sent events: \n";
|
||||
foreach (var entityEvent in sentEvents)
|
||||
{
|
||||
errorMsg += " - " + (entityEvent.Entity?.ToString() ?? "null") + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame2:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
CompressOutgoingMessage(outmsg);
|
||||
server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteClientList(Client c, NetOutgoingMessage outmsg)
|
||||
@@ -1544,8 +1405,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
if (campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode &&
|
||||
NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
|
||||
if (campaign != null && NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
|
||||
{
|
||||
outmsg.Write(true);
|
||||
outmsg.WritePadBits();
|
||||
@@ -1702,23 +1562,9 @@ namespace Barotrauma.Networking
|
||||
Rand.SetSyncedSeed(roundStartSeed);
|
||||
|
||||
int teamCount = 1;
|
||||
MultiPlayerCampaign campaign = selectedMode == GameMain.GameSession?.GameMode.Preset ?
|
||||
MultiPlayerCampaign campaign = GameMain.NetLobbyScreen.SelectedMode == GameMain.GameSession?.GameMode.Preset ?
|
||||
GameMain.GameSession?.GameMode as MultiPlayerCampaign : null;
|
||||
|
||||
if (campaign != null && campaign.Map == null)
|
||||
{
|
||||
initiatedStartGame = false;
|
||||
startGameCoroutine = null;
|
||||
string errorMsg = "Starting the round failed. Campaign was still active, but the map has been disposed. Try selecting another game mode.";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
if (OwnerConnection != null)
|
||||
{
|
||||
SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
|
||||
}
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
//don't instantiate a new gamesession if we're playing a campaign
|
||||
if (campaign == null || GameMain.GameSession == null)
|
||||
{
|
||||
@@ -1743,17 +1589,15 @@ namespace Barotrauma.Networking
|
||||
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
|
||||
|
||||
campaign.AssignClientCharacterInfos(connectedClients);
|
||||
Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Submarine: " + GameMain.GameSession.Submarine.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Level seed: " + campaign.Map.SelectedConnection.Level.Seed, ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.GameSession.StartRound(GameMain.NetLobbyScreen.LevelSeed, serverSettings.SelectedLevelDifficulty, teamCount > 1);
|
||||
Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, ServerLog.MessageType.ServerMessage);
|
||||
|
||||
bool missionAllowRespawn = campaign == null &&
|
||||
(!(GameMain.GameSession.GameMode is MissionMode) ||
|
||||
@@ -1915,7 +1759,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
msg.Write(seed);
|
||||
msg.Write(GameMain.GameSession.Level.Seed);
|
||||
msg.Write(GameMain.GameSession.Level.EqualityCheckVal);
|
||||
msg.Write(serverSettings.SelectedLevelDifficulty);
|
||||
|
||||
msg.Write((byte)GameMain.Config.LosMode);
|
||||
@@ -1977,8 +1820,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
Mission mission = GameMain.GameSession.Mission;
|
||||
GameMain.GameSession.GameMode.End(endMessage);
|
||||
|
||||
endRoundTimer = 0.0f;
|
||||
|
||||
if (serverSettings.AutoRestart)
|
||||
{
|
||||
@@ -2056,7 +1897,14 @@ namespace Barotrauma.Networking
|
||||
public override void AddChatMessage(ChatMessage message)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.Text)) { return; }
|
||||
Log(message.TextWithSender, ServerLog.MessageType.Chat);
|
||||
if (message.Sender != null)
|
||||
{
|
||||
Log($"{message.Sender}: {message.Text}", ServerLog.MessageType.Chat);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"{message.Text}", ServerLog.MessageType.Chat);
|
||||
}
|
||||
|
||||
base.AddChatMessage(message);
|
||||
}
|
||||
@@ -2519,8 +2367,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void SendVoteStatus(List<Client> recipients)
|
||||
{
|
||||
if (!recipients.Any()) { return; }
|
||||
|
||||
NetOutgoingMessage msg = server.CreateMessage();
|
||||
msg.Write((byte)ServerPacketHeader.UPDATE_LOBBY);
|
||||
msg.Write((byte)ServerNetObject.VOTE);
|
||||
@@ -2573,10 +2419,7 @@ namespace Barotrauma.Networking
|
||||
recipients.Add(otherClient.Connection);
|
||||
}
|
||||
}
|
||||
if (recipients.Any())
|
||||
{
|
||||
server.SendMessage(msg, recipients, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
server.SendMessage(msg, recipients, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
|
||||
serverSettings.SaveClientPermissions();
|
||||
}
|
||||
@@ -2610,15 +2453,13 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void UpdateCheatsEnabled()
|
||||
{
|
||||
if (!connectedClients.Any()) { return; }
|
||||
|
||||
var msg = server.CreateMessage();
|
||||
msg.Write((byte)ServerPacketHeader.CHEATS_ENABLED);
|
||||
msg.Write(DebugConsole.CheatsEnabled);
|
||||
msg.WritePadBits();
|
||||
|
||||
CompressOutgoingMessage(msg);
|
||||
|
||||
|
||||
server.SendMessage(msg, connectedClients.Select(c => c.Connection).ToList(), NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -158,15 +158,15 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
//kick connected client if status becomes invalid (e.g. VAC banned, not connected to steam)
|
||||
/*if (status != Facepunch.Steamworks.ServerAuth.Status.OK && GameMain.Config.RequireSteamAuthentication)
|
||||
if (status != Facepunch.Steamworks.ServerAuth.Status.OK && GameMain.Config.RequireSteamAuthentication)
|
||||
{
|
||||
var connectedClient = connectedClients.Find(c => c.SteamID == ownerID);
|
||||
if (connectedClient != null)
|
||||
{
|
||||
Log("Disconnecting client " + connectedClient.Name + " (Steam ID: " + steamID + "). Steam authentication no longer valid (" + status + ").", ServerLog.MessageType.ServerMessage);
|
||||
KickClient(connectedClient, $"DisconnectMessage.SteamAuthNoLongerValid~[status]={status.ToString()}");
|
||||
KickClient(connectedClient, $"DisconnectMessage.SteamAuthNoLongerValid_[status]={status.ToString()}");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsServerOwner(NetIncomingMessage inc, NetConnection senderConnection)
|
||||
@@ -342,7 +342,7 @@ namespace Barotrauma.Networking
|
||||
if (clVersion != GameMain.Version.ToString())
|
||||
{
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.InvalidVersion,
|
||||
$"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={clVersion}");
|
||||
$"DisconnectMessage.InvalidVersion_[version]={GameMain.Version.ToString()}_[clientversion]={clVersion}");
|
||||
|
||||
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", ServerLog.MessageType.Error);
|
||||
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", Color.Red);
|
||||
@@ -368,7 +368,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (missingPackages.Count == 1)
|
||||
{
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}");
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage_[missingcontentpackage]={GetPackageStr(missingPackages[0])}");
|
||||
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content package " + GetPackageStr(missingPackages[0]) + ")", ServerLog.MessageType.Error);
|
||||
return;
|
||||
}
|
||||
@@ -376,7 +376,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
List<string> packageStrs = new List<string>();
|
||||
missingPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}");
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages_[missingcontentpackages]={string.Join(", ", packageStrs)}");
|
||||
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
|
||||
return;
|
||||
}
|
||||
@@ -399,7 +399,7 @@ namespace Barotrauma.Networking
|
||||
if (incompatiblePackages.Count == 1)
|
||||
{
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage,
|
||||
$"DisconnectMessage.IncompatibleContentPackage~[incompatiblecontentpackage]={GetPackageStr2(incompatiblePackages[0])}");
|
||||
$"DisconnectMessage.IncompatibleContentPackage_[incompatiblecontentpackage]={GetPackageStr2(incompatiblePackages[0])}");
|
||||
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content package " + GetPackageStr2(incompatiblePackages[0]) + ")", ServerLog.MessageType.Error);
|
||||
return;
|
||||
}
|
||||
@@ -408,7 +408,7 @@ namespace Barotrauma.Networking
|
||||
List<string> packageStrs = new List<string>();
|
||||
incompatiblePackages.ForEach(cp => packageStrs.Add(GetPackageStr2(cp)));
|
||||
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage,
|
||||
$"DisconnectMessage.IncompatibleContentPackages~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}");
|
||||
$"DisconnectMessage.IncompatibleContentPackages_[incompatiblecontentpackages]={string.Join(", ", packageStrs)}");
|
||||
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
|
||||
return;
|
||||
}
|
||||
@@ -500,7 +500,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private void DisconnectUnauthClient(NetIncomingMessage inc, UnauthenticatedClient unauthClient, DisconnectReason reason, string message)
|
||||
{
|
||||
inc.SenderConnection.Disconnect(reason.ToString() + "/ " + TextManager.GetServerMessage(message));
|
||||
inc.SenderConnection.Disconnect(reason.ToString() + "/ " + message);
|
||||
if (unauthClient.SteamID > 0) { Steam.SteamManager.StopAuthSession(unauthClient.SteamID); }
|
||||
if (unauthClient != null)
|
||||
{
|
||||
|
||||
+35
-14
@@ -1,5 +1,4 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Lidgren.Network;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -209,6 +208,7 @@ namespace Barotrauma.Networking
|
||||
lastSentToAll = owner.LastRecvEntityEventID;
|
||||
}
|
||||
}
|
||||
|
||||
inGameClients.ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.LastRecvEntityEventID)) lastSentToAll = c.LastRecvEntityEventID; });
|
||||
|
||||
clients.Where(c => c.NeedsMidRoundSync).ForEach(c => { if (NetIdUtils.IdMoreRecent(lastSentToAll, c.FirstNewEventID)) lastSentToAll = (ushort)(c.FirstNewEventID - 1); });
|
||||
@@ -228,8 +228,8 @@ namespace Barotrauma.Networking
|
||||
GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected old event "
|
||||
+ (c.LastRecvEntityEventID + 1).ToString() +
|
||||
" (created " + (Timing.TotalTime - firstEventToResend.CreateTime).ToString("0.##") + " s ago)" +
|
||||
" Events queued: " + events.Count + ", last sent to all: " + lastSentToAll, ServerLog.MessageType.Error);
|
||||
server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesyncOldEvent");
|
||||
" Events queued: " + events.Count + ", last sent to all: " + lastSentToAll, ServerLog.MessageType.ServerMessage);
|
||||
server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesync");
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -242,8 +242,8 @@ namespace Barotrauma.Networking
|
||||
toKick.ForEach(c =>
|
||||
{
|
||||
DebugConsole.NewMessage(c.Name + " was kicked due to excessive desync (expected removed event " + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", Color.Red);
|
||||
GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected removed event " + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.Error);
|
||||
server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesyncRemovedEvent");
|
||||
GameServer.Log("Disconnecting client " + c.Name + " due to excessive desync (expected removed event" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.ServerMessage);
|
||||
server.DisconnectClient(c, "", "ServerMessage.ExcessiveDesync");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -251,7 +251,7 @@ namespace Barotrauma.Networking
|
||||
var timedOutClients = clients.FindAll(c => c.InGame && c.NeedsMidRoundSync && Timing.TotalTime > c.MidRoundSyncTimeOut);
|
||||
foreach (Client timedOutClient in timedOutClients)
|
||||
{
|
||||
GameServer.Log("Disconnecting client " + timedOutClient.Name + ". Syncing the client with the server took too long.", ServerLog.MessageType.Error);
|
||||
GameServer.Log("Disconnecting client " + timedOutClient.Name + ". Syncing the client with the server took too long.", ServerLog.MessageType.ServerMessage);
|
||||
GameMain.Server.DisconnectClient(timedOutClient, "", "ServerMessage.SyncTimeout");
|
||||
}
|
||||
|
||||
@@ -305,7 +305,19 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
//too many events for one packet
|
||||
if (eventsToSync.Count > 200)
|
||||
if (eventsToSync.Count > MaxEventsPerWrite)
|
||||
{
|
||||
if (eventsToSync.Count > MaxEventsPerWrite * 3 && !client.NeedsMidRoundSync)
|
||||
{
|
||||
Color color = eventsToSync.Count > MaxEventsPerWrite * 20 ? Color.Red : Color.Orange;
|
||||
if (eventsToSync.Count < MaxEventsPerWrite * 5) { color = Color.Yellow; }
|
||||
DebugConsole.NewMessage("WARNING: event count very high: " + eventsToSync.Count + "/" + MaxEventsPerWrite, color);
|
||||
}
|
||||
|
||||
eventsToSync.RemoveRange(MaxEventsPerWrite, eventsToSync.Count - MaxEventsPerWrite);
|
||||
}
|
||||
|
||||
foreach (NetEntityEvent entityEvent in eventsToSync)
|
||||
{
|
||||
if (eventsToSync.Count > 200 && !client.NeedsMidRoundSync)
|
||||
{
|
||||
@@ -334,11 +346,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (client.NeedsMidRoundSync)
|
||||
{
|
||||
msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL);
|
||||
msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL);
|
||||
|
||||
//how many (unique) events the clients had missed before joining
|
||||
client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count;
|
||||
//ID of the first event sent after the client joined
|
||||
//(after the client has been synced they'll switch their lastReceivedID
|
||||
//to the one before this, and the eventmanagers will start to function "normally")
|
||||
client.FirstNewEventID = events.Count == 0 ? (UInt16)0 : events[events.Count - 1].ID;
|
||||
|
||||
msg.Write(client.UnreceivedEntityEventCount);
|
||||
msg.Write(client.FirstNewEventID);
|
||||
|
||||
Write(msg, eventsToSync, out sentEvents, client);
|
||||
Write(msg, eventsToSync, client);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -351,6 +371,7 @@ namespace Barotrauma.Networking
|
||||
(entityEvent as ServerEntityEvent).Sent = true;
|
||||
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
|
||||
}
|
||||
sentEvents = eventsToSync;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -374,10 +395,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
for (int i = startIndex; i < eventList.Count; i++)
|
||||
{
|
||||
//find the first event that hasn't been sent in roundtriptime or at all
|
||||
client.EntityEventLastSent.TryGetValue(eventList[i].ID, out double lastSent);
|
||||
//find the first event that hasn't been sent in 1.5 * roundtriptime or at all
|
||||
client.EntityEventLastSent.TryGetValue(eventList[i].ID, out float lastSent);
|
||||
|
||||
float minInterval = Math.Max(client.Connection.AverageRoundtripTime, (float)server.UpdateInterval.TotalSeconds * 2);
|
||||
float minInterval = Math.Max(client.Connection.AverageRoundtripTime * 1.5f, (float)server.UpdateInterval.TotalSeconds * 2);
|
||||
|
||||
if (lastSent > NetTime.Now - Math.Min(minInterval, 0.5f))
|
||||
{
|
||||
@@ -403,7 +424,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
double midRoundSyncTimeOut = uniqueEvents.Count / 100 * server.UpdateInterval.TotalSeconds;
|
||||
double midRoundSyncTimeOut = uniqueEvents.Count / MaxEventsPerWrite * server.UpdateInterval.TotalSeconds;
|
||||
midRoundSyncTimeOut = Math.Max(10.0f, midRoundSyncTimeOut * 10.0f);
|
||||
|
||||
client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count;
|
||||
|
||||
@@ -78,7 +78,6 @@ namespace Barotrauma.Networking
|
||||
bool senderSpectating = sender.Character == null || sender.Character.IsDead;
|
||||
|
||||
//spectators cannot speak with in-game players or vice versa
|
||||
//TODO: allow spectators to hear the voice chat if close enough to the speaker?
|
||||
if (recipientSpectating != senderSpectating) { return false; }
|
||||
|
||||
//both spectating, no need to do radio/distance checks
|
||||
|
||||
@@ -116,8 +116,8 @@ namespace Barotrauma
|
||||
msg.Write(AllowEndVoting);
|
||||
if (AllowEndVoting)
|
||||
{
|
||||
msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote<bool>(VoteType.EndRound)));
|
||||
msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned));
|
||||
msg.Write((byte)GameMain.Server.ConnectedClients.Count(v => v.GetVote<bool>(VoteType.EndRound)));
|
||||
msg.Write((byte)GameMain.Server.ConnectedClients.Count);
|
||||
}
|
||||
|
||||
msg.Write(AllowVoteKick);
|
||||
|
||||
Reference in New Issue
Block a user