(965c31410a) Unstable v0.10.4.0
This commit is contained in:
@@ -30,7 +30,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid order message from client \"" + c.Name + "\" - order index out of bounds.");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ namespace Barotrauma.Networking
|
||||
txt = msg.ReadString() ?? "";
|
||||
}
|
||||
|
||||
if (!NetIdUtils.IdMoreRecent(ID, c.LastSentChatMsgID)) return;
|
||||
if (!NetIdUtils.IdMoreRecent(ID, c.LastSentChatMsgID)) { return; }
|
||||
|
||||
c.LastSentChatMsgID = ID;
|
||||
|
||||
@@ -168,6 +169,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
msg.Write(Sender.ID);
|
||||
}
|
||||
if (Type == ChatMessageType.ServerMessageBoxInGame)
|
||||
{
|
||||
msg.Write(IconStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Barotrauma
|
||||
{
|
||||
message.Write((byte)SpawnableType.Item);
|
||||
DebugConsole.Log("Writing item spawn data " + entities.Entity.ToString() + " (original ID: " + entities.OriginalID + ", current ID: " + entities.Entity.ID + ")");
|
||||
((Item)entities.Entity).WriteSpawnData(message, entities.OriginalID, entities.OriginalInventoryID);
|
||||
((Item)entities.Entity).WriteSpawnData(message, entities.OriginalID, entities.OriginalInventoryID, entities.OriginalItemContainerIndex);
|
||||
}
|
||||
else if (entities.Entity is Character)
|
||||
{
|
||||
|
||||
@@ -11,12 +11,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
public class FileTransferOut
|
||||
{
|
||||
private readonly byte[] data;
|
||||
|
||||
private readonly DateTime startingTime;
|
||||
|
||||
private readonly NetworkConnection connection;
|
||||
|
||||
public FileTransferStatus Status;
|
||||
|
||||
public string FileName
|
||||
@@ -48,10 +42,7 @@ namespace Barotrauma.Networking
|
||||
set;
|
||||
}
|
||||
|
||||
public byte[] Data
|
||||
{
|
||||
get { return data; }
|
||||
}
|
||||
public byte[] Data { get; }
|
||||
|
||||
public bool Acknowledged;
|
||||
|
||||
@@ -63,16 +54,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
public int KnownReceivedOffset;
|
||||
|
||||
public NetworkConnection Connection
|
||||
{
|
||||
get { return connection; }
|
||||
}
|
||||
public NetworkConnection Connection { get; }
|
||||
|
||||
public DateTime StartingTime { get; }
|
||||
|
||||
public int ID;
|
||||
|
||||
public FileTransferOut(NetworkConnection recipient, FileTransferType fileType, string filePath)
|
||||
{
|
||||
connection = recipient;
|
||||
Connection = recipient;
|
||||
|
||||
FileType = fileType;
|
||||
FilePath = filePath;
|
||||
@@ -84,14 +74,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
Status = FileTransferStatus.NotStarted;
|
||||
|
||||
startingTime = DateTime.Now;
|
||||
StartingTime = DateTime.Now;
|
||||
|
||||
int maxRetries = 4;
|
||||
for (int i = 0; i <= maxRetries; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
data = File.ReadAllBytes(filePath);
|
||||
Data = File.ReadAllBytes(filePath);
|
||||
}
|
||||
catch (System.IO.IOException e)
|
||||
{
|
||||
@@ -192,97 +182,104 @@ namespace Barotrauma.Networking
|
||||
foreach (FileTransferOut transfer in activeTransfers)
|
||||
{
|
||||
transfer.WaitTimer -= deltaTime;
|
||||
if (transfer.WaitTimer > 0.0f) continue;
|
||||
|
||||
transfer.WaitTimer = 0.05f;// transfer.Connection.AverageRoundtripTime;
|
||||
|
||||
// send another part of the file
|
||||
long remaining = transfer.Data.Length - transfer.SentOffset;
|
||||
int sendByteCount = (remaining > chunkLen ? chunkLen : (int)remaining);
|
||||
|
||||
IWriteMessage message;
|
||||
|
||||
try
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
//first message; send length, file name etc
|
||||
//wait for acknowledgement before sending data
|
||||
if (!transfer.Acknowledged)
|
||||
{
|
||||
message = new WriteOnlyMessage();
|
||||
message.Write((byte)ServerPacketHeader.FILE_TRANSFER);
|
||||
if (transfer.WaitTimer > 0.0f) { break; }
|
||||
Send(transfer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
if (transfer.Connection == GameMain.Server.OwnerConnection)
|
||||
{
|
||||
message.Write((byte)FileTransferMessageType.TransferOnSameMachine);
|
||||
message.Write((byte)transfer.ID);
|
||||
message.Write((byte)transfer.FileType);
|
||||
message.Write(transfer.FilePath);
|
||||
peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
|
||||
transfer.Status = FileTransferStatus.Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
message.Write((byte)FileTransferMessageType.Initiate);
|
||||
message.Write((byte)transfer.ID);
|
||||
message.Write((byte)transfer.FileType);
|
||||
//message.Write((ushort)chunkLen);
|
||||
message.Write(transfer.Data.Length);
|
||||
message.Write(transfer.FileName);
|
||||
peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
|
||||
private void Send(FileTransferOut transfer)
|
||||
{
|
||||
// send another part of the file
|
||||
long remaining = transfer.Data.Length - transfer.SentOffset;
|
||||
int sendByteCount = (remaining > chunkLen ? chunkLen : (int)remaining);
|
||||
|
||||
transfer.Status = FileTransferStatus.Sending;
|
||||
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.Log("Sending file transfer initiation message: ");
|
||||
DebugConsole.Log(" File: " + transfer.FileName);
|
||||
DebugConsole.Log(" Size: " + transfer.Data.Length);
|
||||
DebugConsole.Log(" ID: " + transfer.ID);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
IWriteMessage message;
|
||||
|
||||
try
|
||||
{
|
||||
//first message; send length, file name etc
|
||||
//wait for acknowledgement before sending data
|
||||
if (!transfer.Acknowledged)
|
||||
{
|
||||
message = new WriteOnlyMessage();
|
||||
message.Write((byte)ServerPacketHeader.FILE_TRANSFER);
|
||||
message.Write((byte)FileTransferMessageType.Data);
|
||||
|
||||
message.Write((byte)transfer.ID);
|
||||
message.Write(transfer.SentOffset);
|
||||
|
||||
byte[] sendBytes = new byte[sendByteCount];
|
||||
Array.Copy(transfer.Data, transfer.SentOffset, sendBytes, 0, sendByteCount);
|
||||
|
||||
message.Write((ushort)sendByteCount);
|
||||
message.Write(sendBytes, 0, sendByteCount);
|
||||
|
||||
transfer.SentOffset += sendByteCount;
|
||||
if (transfer.SentOffset > transfer.KnownReceivedOffset + chunkLen * 5 ||
|
||||
transfer.SentOffset >= transfer.Data.Length)
|
||||
//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
|
||||
if (transfer.Connection == GameMain.Server.OwnerConnection)
|
||||
{
|
||||
transfer.SentOffset = transfer.KnownReceivedOffset;
|
||||
message.Write((byte)FileTransferMessageType.TransferOnSameMachine);
|
||||
message.Write((byte)transfer.ID);
|
||||
message.Write((byte)transfer.FileType);
|
||||
message.Write(transfer.FilePath);
|
||||
peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
|
||||
transfer.Status = FileTransferStatus.Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
message.Write((byte)FileTransferMessageType.Initiate);
|
||||
message.Write((byte)transfer.ID);
|
||||
message.Write((byte)transfer.FileType);
|
||||
//message.Write((ushort)chunkLen);
|
||||
message.Write(transfer.Data.Length);
|
||||
message.Write(transfer.FileName);
|
||||
peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
|
||||
|
||||
peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
|
||||
transfer.Status = FileTransferStatus.Sending;
|
||||
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.Log("Sending file transfer initiation message: ");
|
||||
DebugConsole.Log(" File: " + transfer.FileName);
|
||||
DebugConsole.Log(" Size: " + transfer.Data.Length);
|
||||
DebugConsole.Log(" ID: " + transfer.ID);
|
||||
}
|
||||
}
|
||||
transfer.WaitTimer = 0.1f;
|
||||
return;
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
message = new WriteOnlyMessage();
|
||||
message.Write((byte)ServerPacketHeader.FILE_TRANSFER);
|
||||
message.Write((byte)FileTransferMessageType.Data);
|
||||
|
||||
message.Write((byte)transfer.ID);
|
||||
message.Write(transfer.SentOffset);
|
||||
|
||||
byte[] sendBytes = new byte[sendByteCount];
|
||||
Array.Copy(transfer.Data, transfer.SentOffset, sendBytes, 0, sendByteCount);
|
||||
|
||||
message.Write((ushort)sendByteCount);
|
||||
message.Write(sendBytes, 0, sendByteCount);
|
||||
|
||||
transfer.SentOffset += sendByteCount;
|
||||
if (transfer.SentOffset > transfer.KnownReceivedOffset + chunkLen * 10 ||
|
||||
transfer.SentOffset >= transfer.Data.Length)
|
||||
{
|
||||
DebugConsole.ThrowError("FileSender threw an exception when trying to send data", e);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"FileSender.Update:Exception",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace);
|
||||
transfer.Status = FileTransferStatus.Error;
|
||||
break;
|
||||
transfer.SentOffset = transfer.KnownReceivedOffset;
|
||||
transfer.WaitTimer = 0.5f;
|
||||
}
|
||||
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.Log("Sending " + sendByteCount + " bytes of the file " + transfer.FileName + " (" + transfer.SentOffset + "/" + transfer.Data.Length + " sent)");
|
||||
}
|
||||
peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("FileSender threw an exception when trying to send data", e);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"FileSender.Update:Exception",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace);
|
||||
transfer.Status = FileTransferStatus.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.Log($"Sending {sendByteCount} bytes of the file {transfer.FileName} ({transfer.SentOffset / 1000}/{transfer.Data.Length / 1000} kB sent)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +314,11 @@ namespace Barotrauma.Networking
|
||||
matchingTransfer.Acknowledged = true;
|
||||
int offset = inc.ReadInt32();
|
||||
matchingTransfer.KnownReceivedOffset = offset > matchingTransfer.KnownReceivedOffset ? offset : matchingTransfer.KnownReceivedOffset;
|
||||
if (matchingTransfer.SentOffset < matchingTransfer.KnownReceivedOffset) { matchingTransfer.SentOffset = matchingTransfer.KnownReceivedOffset; }
|
||||
if (matchingTransfer.SentOffset < matchingTransfer.KnownReceivedOffset)
|
||||
{
|
||||
matchingTransfer.WaitTimer = 0.0f;
|
||||
matchingTransfer.SentOffset = matchingTransfer.KnownReceivedOffset;
|
||||
}
|
||||
|
||||
if (matchingTransfer.KnownReceivedOffset >= matchingTransfer.Data.Length)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -255,8 +255,8 @@ namespace Barotrauma.Networking
|
||||
(firstEventToResend.CreateTime > c.MidRoundSyncTimeOut || lastSentToAnyoneTime > c.MidRoundSyncTimeOut || Timing.TotalTime > c.MidRoundSyncTimeOut + 10.0));
|
||||
toKick.ForEach(c =>
|
||||
{
|
||||
DebugConsole.NewMessage(c.Name + " was kicked due to excessive desync (expected old event " + (c.LastRecvEntityEventID + 1).ToString() + ")", Color.Red);
|
||||
GameServer.Log("Disconnecting client " + GameServer.ClientLogName(c) + " due to excessive desync (expected old event "
|
||||
DebugConsole.NewMessage(c.Name + " was kicked because they were expecting a very old network event (" + (c.LastRecvEntityEventID + 1).ToString() + ")", Color.Red);
|
||||
GameServer.Log(GameServer.ClientLogName(c) + " was kicked because they were expecting a very old network event ("
|
||||
+ (c.LastRecvEntityEventID + 1).ToString() +
|
||||
" (created " + (Timing.TotalTime - firstEventToResend.CreateTime).ToString("0.##") + " s ago, " +
|
||||
(lastSentToAnyoneTime - firstEventToResend.CreateTime).ToString("0.##") + " s older than last event sent to anyone)" +
|
||||
@@ -273,8 +273,8 @@ namespace Barotrauma.Networking
|
||||
List<Client> toKick = inGameClients.FindAll(c => NetIdUtils.IdMoreRecent(events[0].ID, (UInt16)(c.LastRecvEntityEventID + 1)));
|
||||
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 " + GameServer.ClientLogName(c) + " due to excessive desync (expected removed event " + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.Error);
|
||||
DebugConsole.NewMessage(c.Name + " was kicked because they were expecting a removed network event (" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", Color.Red);
|
||||
GameServer.Log(GameServer.ClientLogName(c) + " was kicked because they were expecting a removed network event (" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.Error);
|
||||
server.DisconnectClient(c, "", DisconnectReason.ExcessiveDesyncRemovedEvent + "/ServerMessage.ExcessiveDesyncRemovedEvent");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Barotrauma.Networking
|
||||
partial class ServerSettings
|
||||
{
|
||||
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml";
|
||||
public static readonly char SubmarineSeparatorChar = '|';
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
|
||||
@@ -16,6 +16,51 @@ namespace Barotrauma
|
||||
{
|
||||
get { return allowModeVoting; }
|
||||
set { allowModeVoting = value; }
|
||||
}
|
||||
|
||||
public struct SubmarineVote
|
||||
{
|
||||
public Client VoteStarter;
|
||||
public SubmarineInfo Sub;
|
||||
public VoteType VoteType;
|
||||
public float Timer;
|
||||
public int DeliveryFee;
|
||||
public VoteState State;
|
||||
}
|
||||
|
||||
public static SubmarineVote SubVote;
|
||||
|
||||
private void StartSubmarineVote(IReadMessage inc, VoteType voteType, Client sender)
|
||||
{
|
||||
string subName = inc.ReadString();
|
||||
SubVote.Sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
|
||||
SubVote.DeliveryFee = voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0;
|
||||
SubVote.VoteType = voteType;
|
||||
SubVote.State = VoteState.Started;
|
||||
SubVote.VoteStarter = sender;
|
||||
VoteRunning = true;
|
||||
sender.SetVote(voteType, 2);
|
||||
}
|
||||
|
||||
public void StopSubmarineVote(bool passed)
|
||||
{
|
||||
VoteRunning = false;
|
||||
SubVote.State = passed ? VoteState.Passed : VoteState.Failed;
|
||||
|
||||
GameMain.Server.UpdateVoteStatus();
|
||||
|
||||
GameMain.NetworkMember.SubmarineVoteYesCount = GameMain.NetworkMember.SubmarineVoteNoCount = GameMain.NetworkMember.SubmarineVoteMax = 0;
|
||||
for (int i = 0; i < GameMain.NetworkMember.ConnectedClients.Count; i++)
|
||||
{
|
||||
GameMain.NetworkMember.ConnectedClients[i].SetVote(SubVote.VoteType, 0);
|
||||
}
|
||||
|
||||
SubVote.Sub = null;
|
||||
SubVote.DeliveryFee = 0;
|
||||
SubVote.VoteType = VoteType.Unknown;
|
||||
SubVote.Timer = 0.0f;
|
||||
SubVote.State = VoteState.None;
|
||||
SubVote.VoteStarter = null;
|
||||
}
|
||||
|
||||
public void ServerRead(IReadMessage inc, Client sender)
|
||||
@@ -76,7 +121,24 @@ namespace Barotrauma
|
||||
sender.SetVote(VoteType.StartRound, ready);
|
||||
GameServer.Log(GameServer.ClientLogName(sender) + (ready ? " is ready to start the game." : " is not ready to start the game."), ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
break;
|
||||
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
case VoteType.PurchaseSub:
|
||||
case VoteType.SwitchSub:
|
||||
bool startVote = inc.ReadBoolean();
|
||||
if (startVote)
|
||||
{
|
||||
StartSubmarineVote(inc, voteType, sender);
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.SetVote(voteType, (int)inc.ReadByte());
|
||||
}
|
||||
|
||||
GameMain.Server.SubmarineVoteYesCount = GameMain.Server.ConnectedClients.Count(c => c.GetVote<int>(SubVote.VoteType) == 2);
|
||||
GameMain.Server.SubmarineVoteNoCount = GameMain.Server.ConnectedClients.Count(c => c.GetVote<int>(SubVote.VoteType) == 1);
|
||||
GameMain.Server.SubmarineVoteMax = GameMain.Server.ConnectedClients.Count(c => c.InGame);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -120,6 +182,52 @@ namespace Barotrauma
|
||||
|
||||
msg.Write(AllowVoteKick);
|
||||
|
||||
msg.Write((byte)SubVote.State);
|
||||
if (SubVote.State != VoteState.None)
|
||||
{
|
||||
msg.Write((byte)SubVote.VoteType);
|
||||
|
||||
if (SubVote.VoteType != VoteType.Unknown)
|
||||
{
|
||||
var yesClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote<int>(SubVote.VoteType) == 2);
|
||||
msg.Write((byte)yesClients.Count);
|
||||
foreach (Client c in yesClients)
|
||||
{
|
||||
msg.Write(c.ID);
|
||||
}
|
||||
|
||||
var noClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote<int>(SubVote.VoteType) == 1);
|
||||
msg.Write((byte)noClients.Count);
|
||||
foreach (Client c in noClients)
|
||||
{
|
||||
msg.Write(c.ID);
|
||||
}
|
||||
|
||||
msg.Write((byte)GameMain.Server.SubmarineVoteMax);
|
||||
|
||||
switch (SubVote.State)
|
||||
{
|
||||
case VoteState.Started:
|
||||
msg.Write(SubVote.Sub.Name);
|
||||
msg.Write(SubVote.VoteStarter.ID);
|
||||
msg.Write((byte)GameMain.Server.ServerSettings.SubmarineVoteTimeout);
|
||||
break;
|
||||
case VoteState.Running:
|
||||
// Nothing specific
|
||||
break;
|
||||
case VoteState.Passed:
|
||||
case VoteState.Failed:
|
||||
msg.Write(SubVote.State == VoteState.Passed);
|
||||
msg.Write(SubVote.Sub.Name);
|
||||
if (SubVote.State == VoteState.Passed)
|
||||
{
|
||||
msg.Write((short)SubVote.DeliveryFee);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var readyClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote<bool>(VoteType.StartRound));
|
||||
msg.Write((byte)readyClients.Count);
|
||||
foreach (Client c in readyClients)
|
||||
|
||||
Reference in New Issue
Block a user