Build 0.20.8.0
This commit is contained in:
@@ -200,9 +200,9 @@ namespace Barotrauma.Networking
|
||||
return length;
|
||||
}
|
||||
|
||||
public virtual void ServerWrite(IWriteMessage msg, Client c)
|
||||
public virtual void ServerWrite(in SegmentTableWriter<ServerNetSegment> segmentTable, IWriteMessage msg, Client c)
|
||||
{
|
||||
msg.WriteByte((byte)ServerNetObject.CHAT_MESSAGE);
|
||||
segmentTable.StartNewSegment(ServerNetSegment.ChatMessage);
|
||||
msg.WriteUInt16(NetStateID);
|
||||
msg.WriteRangedInteger((int)Type, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
msg.WriteByte((byte)ChangeType);
|
||||
|
||||
@@ -1028,12 +1028,11 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
ClientNetObject objHeader;
|
||||
while ((objHeader = (ClientNetObject)inc.ReadByte()) != ClientNetObject.END_OF_MESSAGE)
|
||||
SegmentTableReader<ClientNetSegment>.Read(inc, (segment, inc) =>
|
||||
{
|
||||
switch (objHeader)
|
||||
switch (segment)
|
||||
{
|
||||
case ClientNetObject.SYNC_IDS:
|
||||
case ClientNetSegment.SyncIds:
|
||||
//TODO: might want to use a clever class for this
|
||||
c.LastRecvLobbyUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvLobbyUpdate, GameMain.NetLobbyScreen.LastUpdateID);
|
||||
if (c.HasPermission(ClientPermissions.ManageSettings) &&
|
||||
@@ -1072,19 +1071,21 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ClientNetObject.CHAT_MESSAGE:
|
||||
case ClientNetSegment.ChatMessage:
|
||||
ChatMessage.ServerRead(inc, c);
|
||||
break;
|
||||
case ClientNetObject.VOTE:
|
||||
case ClientNetSegment.Vote:
|
||||
Voting.ServerRead(inc, c);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return SegmentTableReader<ClientNetSegment>.BreakSegmentReading.Yes;
|
||||
}
|
||||
|
||||
//don't read further messages if the client has been disconnected (kicked due to spam for example)
|
||||
if (!connectedClients.Contains(c)) break;
|
||||
}
|
||||
return connectedClients.Contains(c)
|
||||
? SegmentTableReader<ClientNetSegment>.BreakSegmentReading.No
|
||||
: SegmentTableReader<ClientNetSegment>.BreakSegmentReading.Yes;
|
||||
});
|
||||
}
|
||||
|
||||
private void ClientReadIngame(IReadMessage inc)
|
||||
@@ -1109,13 +1110,12 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
ClientNetObject objHeader;
|
||||
while ((objHeader = (ClientNetObject)inc.ReadByte()) != ClientNetObject.END_OF_MESSAGE)
|
||||
SegmentTableReader<ClientNetSegment>.Read(inc, (segment, inc) =>
|
||||
{
|
||||
switch (objHeader)
|
||||
switch (segment)
|
||||
{
|
||||
case ClientNetObject.SYNC_IDS:
|
||||
//TODO: might want to use a clever class for this
|
||||
case ClientNetSegment.SyncIds:
|
||||
//TODO: switch this to INetSerializableStruct
|
||||
|
||||
UInt16 lastRecvChatMsgID = inc.ReadUInt16();
|
||||
UInt16 lastRecvEntityEventID = inc.ReadUInt16();
|
||||
@@ -1218,10 +1218,10 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
break;
|
||||
case ClientNetObject.CHAT_MESSAGE:
|
||||
case ClientNetSegment.ChatMessage:
|
||||
ChatMessage.ServerRead(inc, c);
|
||||
break;
|
||||
case ClientNetObject.CHARACTER_INPUT:
|
||||
case ClientNetSegment.CharacterInput:
|
||||
if (c.Character != null)
|
||||
{
|
||||
c.Character.ServerReadInput(inc, c);
|
||||
@@ -1231,22 +1231,24 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.AddWarning($"Received character inputs from a client who's not controlling a character ({c.Name}).");
|
||||
}
|
||||
break;
|
||||
case ClientNetObject.ENTITY_STATE:
|
||||
case ClientNetSegment.EntityState:
|
||||
entityEventManager.Read(inc, c);
|
||||
break;
|
||||
case ClientNetObject.VOTE:
|
||||
case ClientNetSegment.Vote:
|
||||
Voting.ServerRead(inc, c);
|
||||
break;
|
||||
case ClientNetObject.SPECTATING_POS:
|
||||
case ClientNetSegment.SpectatingPos:
|
||||
c.SpectatePos = new Vector2(inc.ReadSingle(), inc.ReadSingle());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return SegmentTableReader<ClientNetSegment>.BreakSegmentReading.Yes;
|
||||
}
|
||||
|
||||
//don't read further messages if the client has been disconnected (kicked due to spam for example)
|
||||
if (!connectedClients.Contains(c)) { break; }
|
||||
}
|
||||
return connectedClients.Contains(c)
|
||||
? SegmentTableReader<ClientNetSegment>.BreakSegmentReading.No
|
||||
: SegmentTableReader<ClientNetSegment>.BreakSegmentReading.Yes;
|
||||
});
|
||||
}
|
||||
|
||||
private void ReadCrewMessage(IReadMessage inc, Client sender)
|
||||
@@ -1701,78 +1703,78 @@ namespace Barotrauma.Networking
|
||||
|
||||
IWriteMessage outmsg = new WriteOnlyMessage();
|
||||
outmsg.WriteByte((byte)ServerPacketHeader.UPDATE_INGAME);
|
||||
|
||||
outmsg.WriteSingle((float)NetTime.Now);
|
||||
|
||||
outmsg.WriteByte((byte)ServerNetObject.SYNC_IDS);
|
||||
outmsg.WriteUInt16(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
|
||||
outmsg.WriteUInt16(c.LastSentEntityEventID);
|
||||
|
||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||
using (var segmentTable = SegmentTableWriter<ServerNetSegment>.StartWriting(outmsg))
|
||||
{
|
||||
outmsg.WriteBoolean(true);
|
||||
outmsg.WritePadBits();
|
||||
campaign.ServerWrite(outmsg, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
outmsg.WriteBoolean(false);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
segmentTable.StartNewSegment(ServerNetSegment.SyncIds);
|
||||
outmsg.WriteUInt16(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
|
||||
outmsg.WriteUInt16(c.LastSentEntityEventID);
|
||||
|
||||
int clientListBytes = outmsg.LengthBytes;
|
||||
WriteClientList(c, outmsg);
|
||||
clientListBytes = outmsg.LengthBytes - clientListBytes;
|
||||
|
||||
int chatMessageBytes = outmsg.LengthBytes;
|
||||
WriteChatMessages(outmsg, c);
|
||||
chatMessageBytes = outmsg.LengthBytes - chatMessageBytes;
|
||||
|
||||
//write as many position updates as the message can fit (only after midround syncing is done)
|
||||
int positionUpdateBytes = outmsg.LengthBytes;
|
||||
while (!c.NeedsMidRoundSync && c.PendingPositionUpdates.Count > 0)
|
||||
{
|
||||
var entity = c.PendingPositionUpdates.Peek();
|
||||
if (!(entity is IServerPositionSync entityPositionSync) ||
|
||||
entity.Removed ||
|
||||
(entity is Item item && float.IsInfinity(item.PositionUpdateInterval)))
|
||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||
{
|
||||
outmsg.WriteBoolean(true);
|
||||
outmsg.WritePadBits();
|
||||
campaign.ServerWrite(outmsg, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
outmsg.WriteBoolean(false);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
|
||||
int clientListBytes = outmsg.LengthBytes;
|
||||
WriteClientList(segmentTable, c, outmsg);
|
||||
clientListBytes = outmsg.LengthBytes - clientListBytes;
|
||||
|
||||
int chatMessageBytes = outmsg.LengthBytes;
|
||||
WriteChatMessages(segmentTable, outmsg, c);
|
||||
chatMessageBytes = outmsg.LengthBytes - chatMessageBytes;
|
||||
|
||||
//write as many position updates as the message can fit (only after midround syncing is done)
|
||||
int positionUpdateBytes = outmsg.LengthBytes;
|
||||
while (!c.NeedsMidRoundSync && c.PendingPositionUpdates.Count > 0)
|
||||
{
|
||||
var entity = c.PendingPositionUpdates.Peek();
|
||||
if (!(entity is IServerPositionSync entityPositionSync) ||
|
||||
entity.Removed ||
|
||||
(entity is Item item && float.IsInfinity(item.PositionUpdateInterval)))
|
||||
{
|
||||
c.PendingPositionUpdates.Dequeue();
|
||||
continue;
|
||||
}
|
||||
|
||||
IWriteMessage tempBuffer = new ReadWriteMessage();
|
||||
tempBuffer.WriteBoolean(entity is Item); tempBuffer.WritePadBits();
|
||||
tempBuffer.WriteUInt32(entity is MapEntity me ? me.Prefab.UintIdentifier : (UInt32)0);
|
||||
entityPositionSync.ServerWritePosition(tempBuffer, c);
|
||||
|
||||
//no more room in this packet
|
||||
if (outmsg.LengthBytes + tempBuffer.LengthBytes > MsgConstants.MTU - 100)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
segmentTable.StartNewSegment(ServerNetSegment.EntityPosition);
|
||||
outmsg.WritePadBits(); //padding is required here to make sure any padding bits within tempBuffer are read correctly
|
||||
outmsg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
outmsg.WritePadBits();
|
||||
|
||||
c.PositionUpdateLastSent[entity] = (float)NetTime.Now;
|
||||
c.PendingPositionUpdates.Dequeue();
|
||||
continue;
|
||||
}
|
||||
positionUpdateBytes = outmsg.LengthBytes - positionUpdateBytes;
|
||||
|
||||
IWriteMessage tempBuffer = new ReadWriteMessage();
|
||||
tempBuffer.WriteBoolean(entity is Item); tempBuffer.WritePadBits();
|
||||
tempBuffer.WriteUInt32(entity is MapEntity me ? me.Prefab.UintIdentifier : (UInt32)0);
|
||||
entityPositionSync.ServerWritePosition(tempBuffer, c);
|
||||
|
||||
//no more room in this packet
|
||||
if (outmsg.LengthBytes + tempBuffer.LengthBytes > MsgConstants.MTU - 100)
|
||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
||||
{
|
||||
break;
|
||||
string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||
errorMsg +=
|
||||
" Client list size: " + clientListBytes + " bytes\n" +
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Position update size: " + positionUpdateBytes + " bytes\n\n";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
outmsg.WriteByte((byte)ServerNetObject.ENTITY_POSITION);
|
||||
outmsg.WritePadBits(); //padding is required here to make sure any padding bits within tempBuffer are read correctly
|
||||
outmsg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
outmsg.WritePadBits();
|
||||
|
||||
c.PositionUpdateLastSent[entity] = (float)NetTime.Now;
|
||||
c.PendingPositionUpdates.Dequeue();
|
||||
}
|
||||
positionUpdateBytes = outmsg.LengthBytes - positionUpdateBytes;
|
||||
|
||||
outmsg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
|
||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
||||
{
|
||||
string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||
errorMsg +=
|
||||
" Client list size: " + clientListBytes + " bytes\n" +
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Position update size: " + positionUpdateBytes + " bytes\n\n";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||
@@ -1785,46 +1787,50 @@ namespace Barotrauma.Networking
|
||||
outmsg.WriteByte((byte)ServerPacketHeader.UPDATE_INGAME);
|
||||
outmsg.WriteSingle((float)Lidgren.Network.NetTime.Now);
|
||||
|
||||
int eventManagerBytes = outmsg.LengthBytes;
|
||||
entityEventManager.Write(c, outmsg, out List<NetEntityEvent> sentEvents);
|
||||
eventManagerBytes = outmsg.LengthBytes - eventManagerBytes;
|
||||
|
||||
if (sentEvents.Count == 0)
|
||||
using (var segmentTable = SegmentTableWriter<ServerNetSegment>.StartWriting(outmsg))
|
||||
{
|
||||
break;
|
||||
}
|
||||
int eventManagerBytes = outmsg.LengthBytes;
|
||||
entityEventManager.Write(segmentTable, c, outmsg, out List<NetEntityEvent> sentEvents);
|
||||
eventManagerBytes = outmsg.LengthBytes - eventManagerBytes;
|
||||
|
||||
outmsg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
|
||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
||||
{
|
||||
string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||
errorMsg +=
|
||||
" Event size: " + eventManagerBytes + " bytes\n";
|
||||
|
||||
if (sentEvents != null && sentEvents.Count > 0)
|
||||
if (sentEvents.Count == 0)
|
||||
{
|
||||
errorMsg += "Sent events: \n";
|
||||
foreach (var entityEvent in sentEvents)
|
||||
{
|
||||
errorMsg += " - " + (entityEvent.Entity?.ToString() ?? "null") + "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame2:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
||||
{
|
||||
string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " +
|
||||
MsgConstants.MTU + ")\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,
|
||||
GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteClientList(Client c, IWriteMessage outmsg)
|
||||
private void WriteClientList(in SegmentTableWriter<ServerNetSegment> segmentTable, Client c, IWriteMessage outmsg)
|
||||
{
|
||||
bool hasChanged = NetIdUtils.IdMoreRecent(LastClientListUpdateID, c.LastRecvClientListUpdate);
|
||||
if (!hasChanged) { return; }
|
||||
|
||||
outmsg.WriteByte((byte)ServerNetObject.CLIENT_LIST);
|
||||
segmentTable.StartNewSegment(ServerNetSegment.ClientList);
|
||||
outmsg.WriteUInt16(LastClientListUpdateID);
|
||||
|
||||
outmsg.WriteByte((byte)connectedClients.Count);
|
||||
@@ -1861,133 +1867,135 @@ namespace Barotrauma.Networking
|
||||
IWriteMessage outmsg = new WriteOnlyMessage();
|
||||
outmsg.WriteByte((byte)ServerPacketHeader.UPDATE_LOBBY);
|
||||
|
||||
outmsg.WriteByte((byte)ServerNetObject.SYNC_IDS);
|
||||
|
||||
int settingsBytes = outmsg.LengthBytes;
|
||||
int initialUpdateBytes = 0;
|
||||
|
||||
if (ServerSettings.UnsentFlags() != ServerSettings.NetFlags.None)
|
||||
bool messageTooLarge;
|
||||
using (var segmentTable = SegmentTableWriter<ServerNetSegment>.StartWriting(outmsg))
|
||||
{
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
}
|
||||
|
||||
IWriteMessage settingsBuf = null;
|
||||
if (NetIdUtils.IdMoreRecent(GameMain.NetLobbyScreen.LastUpdateID, c.LastRecvLobbyUpdate))
|
||||
{
|
||||
outmsg.WriteBoolean(true);
|
||||
outmsg.WritePadBits();
|
||||
segmentTable.StartNewSegment(ServerNetSegment.SyncIds);
|
||||
|
||||
outmsg.WriteUInt16(GameMain.NetLobbyScreen.LastUpdateID);
|
||||
int settingsBytes = outmsg.LengthBytes;
|
||||
int initialUpdateBytes = 0;
|
||||
|
||||
settingsBuf = new ReadWriteMessage();
|
||||
ServerSettings.ServerWrite(settingsBuf, c);
|
||||
outmsg.WriteUInt16((UInt16)settingsBuf.LengthBytes);
|
||||
outmsg.WriteBytes(settingsBuf.Buffer, 0, settingsBuf.LengthBytes);
|
||||
|
||||
outmsg.WriteBoolean(c.LastRecvLobbyUpdate < 1);
|
||||
if (c.LastRecvLobbyUpdate < 1)
|
||||
if (ServerSettings.UnsentFlags() != ServerSettings.NetFlags.None)
|
||||
{
|
||||
isInitialUpdate = true;
|
||||
initialUpdateBytes = outmsg.LengthBytes;
|
||||
ClientWriteInitial(c, outmsg);
|
||||
initialUpdateBytes = outmsg.LengthBytes - initialUpdateBytes;
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
}
|
||||
outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.Name);
|
||||
outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.MD5Hash.ToString());
|
||||
outmsg.WriteBoolean(IsUsingRespawnShuttle());
|
||||
var selectedShuttle = GameStarted && RespawnManager != null && RespawnManager.UsingShuttle ?
|
||||
RespawnManager.RespawnShuttle.Info :
|
||||
GameMain.NetLobbyScreen.SelectedShuttle;
|
||||
outmsg.WriteString(selectedShuttle.Name);
|
||||
outmsg.WriteString(selectedShuttle.MD5Hash.ToString());
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.AllowSubVoting);
|
||||
outmsg.WriteBoolean(ServerSettings.AllowModeVoting);
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.VoiceChatEnabled);
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.AllowSpectating);
|
||||
|
||||
outmsg.WriteRangedInteger((int)ServerSettings.TraitorsEnabled, 0, 2);
|
||||
|
||||
outmsg.WriteRangedInteger((int)GameMain.NetLobbyScreen.MissionType, 0, (int)MissionType.All);
|
||||
|
||||
outmsg.WriteByte((byte)GameMain.NetLobbyScreen.SelectedModeIndex);
|
||||
outmsg.WriteString(GameMain.NetLobbyScreen.LevelSeed);
|
||||
outmsg.WriteSingle(ServerSettings.SelectedLevelDifficulty);
|
||||
|
||||
outmsg.WriteByte((byte)ServerSettings.BotCount);
|
||||
outmsg.WriteBoolean(ServerSettings.BotSpawnMode == BotSpawnMode.Fill);
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.AutoRestart);
|
||||
if (ServerSettings.AutoRestart)
|
||||
IWriteMessage settingsBuf = null;
|
||||
if (NetIdUtils.IdMoreRecent(GameMain.NetLobbyScreen.LastUpdateID, c.LastRecvLobbyUpdate))
|
||||
{
|
||||
outmsg.WriteSingle(autoRestartTimerRunning ? ServerSettings.AutoRestartTimer : 0.0f);
|
||||
outmsg.WriteBoolean(true);
|
||||
outmsg.WritePadBits();
|
||||
|
||||
outmsg.WriteUInt16(GameMain.NetLobbyScreen.LastUpdateID);
|
||||
|
||||
settingsBuf = new ReadWriteMessage();
|
||||
ServerSettings.ServerWrite(settingsBuf, c);
|
||||
outmsg.WriteUInt16((UInt16)settingsBuf.LengthBytes);
|
||||
outmsg.WriteBytes(settingsBuf.Buffer, 0, settingsBuf.LengthBytes);
|
||||
|
||||
outmsg.WriteBoolean(c.LastRecvLobbyUpdate < 1);
|
||||
if (c.LastRecvLobbyUpdate < 1)
|
||||
{
|
||||
isInitialUpdate = true;
|
||||
initialUpdateBytes = outmsg.LengthBytes;
|
||||
ClientWriteInitial(c, outmsg);
|
||||
initialUpdateBytes = outmsg.LengthBytes - initialUpdateBytes;
|
||||
}
|
||||
outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.Name);
|
||||
outmsg.WriteString(GameMain.NetLobbyScreen.SelectedSub.MD5Hash.ToString());
|
||||
outmsg.WriteBoolean(IsUsingRespawnShuttle());
|
||||
var selectedShuttle = GameStarted && RespawnManager != null && RespawnManager.UsingShuttle ?
|
||||
RespawnManager.RespawnShuttle.Info :
|
||||
GameMain.NetLobbyScreen.SelectedShuttle;
|
||||
outmsg.WriteString(selectedShuttle.Name);
|
||||
outmsg.WriteString(selectedShuttle.MD5Hash.ToString());
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.AllowSubVoting);
|
||||
outmsg.WriteBoolean(ServerSettings.AllowModeVoting);
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.VoiceChatEnabled);
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.AllowSpectating);
|
||||
|
||||
outmsg.WriteRangedInteger((int)ServerSettings.TraitorsEnabled, 0, 2);
|
||||
|
||||
outmsg.WriteRangedInteger((int)GameMain.NetLobbyScreen.MissionType, 0, (int)MissionType.All);
|
||||
|
||||
outmsg.WriteByte((byte)GameMain.NetLobbyScreen.SelectedModeIndex);
|
||||
outmsg.WriteString(GameMain.NetLobbyScreen.LevelSeed);
|
||||
outmsg.WriteSingle(ServerSettings.SelectedLevelDifficulty);
|
||||
|
||||
outmsg.WriteByte((byte)ServerSettings.BotCount);
|
||||
outmsg.WriteBoolean(ServerSettings.BotSpawnMode == BotSpawnMode.Fill);
|
||||
|
||||
outmsg.WriteBoolean(ServerSettings.AutoRestart);
|
||||
if (ServerSettings.AutoRestart)
|
||||
{
|
||||
outmsg.WriteSingle(autoRestartTimerRunning ? ServerSettings.AutoRestartTimer : 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outmsg.WriteBoolean(false);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
settingsBytes = outmsg.LengthBytes - settingsBytes;
|
||||
|
||||
int campaignBytes = outmsg.LengthBytes;
|
||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
if (outmsg.LengthBytes < MsgConstants.MTU - 500 &&
|
||||
campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||
{
|
||||
outmsg.WriteBoolean(true);
|
||||
outmsg.WritePadBits();
|
||||
campaign.ServerWrite(outmsg, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
outmsg.WriteBoolean(false);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
campaignBytes = outmsg.LengthBytes - campaignBytes;
|
||||
|
||||
outmsg.WriteUInt16(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
|
||||
|
||||
int clientListBytes = outmsg.LengthBytes;
|
||||
if (outmsg.LengthBytes < MsgConstants.MTU - 500)
|
||||
{
|
||||
WriteClientList(c, outmsg);
|
||||
}
|
||||
clientListBytes = outmsg.LengthBytes - clientListBytes;
|
||||
|
||||
int chatMessageBytes = outmsg.LengthBytes;
|
||||
WriteChatMessages(outmsg, c);
|
||||
chatMessageBytes = outmsg.LengthBytes - chatMessageBytes;
|
||||
|
||||
outmsg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
|
||||
bool messageTooLarge = outmsg.LengthBytes > MsgConstants.MTU;
|
||||
if (messageTooLarge && !isInitialUpdate)
|
||||
{
|
||||
string warningMsg = "Maximum packet size exceeded, will send using reliable mode (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||
warningMsg +=
|
||||
" Client list size: " + clientListBytes + " bytes\n" +
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Campaign size: " + campaignBytes + " bytes\n" +
|
||||
" Settings size: " + settingsBytes + " bytes\n";
|
||||
if (initialUpdateBytes > 0)
|
||||
else
|
||||
{
|
||||
outmsg.WriteBoolean(false);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
settingsBytes = outmsg.LengthBytes - settingsBytes;
|
||||
|
||||
int campaignBytes = outmsg.LengthBytes;
|
||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
if (outmsg.LengthBytes < MsgConstants.MTU - 500 &&
|
||||
campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||
{
|
||||
outmsg.WriteBoolean(true);
|
||||
outmsg.WritePadBits();
|
||||
campaign.ServerWrite(outmsg, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
outmsg.WriteBoolean(false);
|
||||
outmsg.WritePadBits();
|
||||
}
|
||||
campaignBytes = outmsg.LengthBytes - campaignBytes;
|
||||
|
||||
outmsg.WriteUInt16(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
|
||||
|
||||
int clientListBytes = outmsg.LengthBytes;
|
||||
if (outmsg.LengthBytes < MsgConstants.MTU - 500)
|
||||
{
|
||||
WriteClientList(segmentTable, c, outmsg);
|
||||
}
|
||||
clientListBytes = outmsg.LengthBytes - clientListBytes;
|
||||
|
||||
int chatMessageBytes = outmsg.LengthBytes;
|
||||
WriteChatMessages(segmentTable, outmsg, c);
|
||||
chatMessageBytes = outmsg.LengthBytes - chatMessageBytes;
|
||||
|
||||
messageTooLarge = outmsg.LengthBytes > MsgConstants.MTU;
|
||||
if (messageTooLarge && !isInitialUpdate)
|
||||
{
|
||||
string warningMsg = "Maximum packet size exceeded, will send using reliable mode (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||
warningMsg +=
|
||||
" Initial update size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||
}
|
||||
if (settingsBuf != null)
|
||||
{
|
||||
warningMsg +=
|
||||
" Settings buffer size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||
}
|
||||
" Client list size: " + clientListBytes + " bytes\n" +
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Campaign size: " + campaignBytes + " bytes\n" +
|
||||
" Settings size: " + settingsBytes + " bytes\n";
|
||||
if (initialUpdateBytes > 0)
|
||||
{
|
||||
warningMsg +=
|
||||
" Initial update size: " + initialUpdateBytes + " bytes\n";
|
||||
}
|
||||
if (settingsBuf != null)
|
||||
{
|
||||
warningMsg +=
|
||||
" Settings buffer size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||
}
|
||||
#if DEBUG || UNSTABLE
|
||||
DebugConsole.ThrowError(warningMsg);
|
||||
DebugConsole.ThrowError(warningMsg);
|
||||
#else
|
||||
if (GameSettings.CurrentConfig.VerboseLogging) { DebugConsole.AddWarning(warningMsg); }
|
||||
if (GameSettings.CurrentConfig.VerboseLogging) { DebugConsole.AddWarning(warningMsg); }
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:ClientWriteLobby" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Warning, warningMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:ClientWriteLobby" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Warning, warningMsg);
|
||||
}
|
||||
}
|
||||
|
||||
if (isInitialUpdate || messageTooLarge)
|
||||
@@ -2014,7 +2022,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteChatMessages(IWriteMessage outmsg, Client c)
|
||||
private void WriteChatMessages(in SegmentTableWriter<ServerNetSegment> segmentTable, IWriteMessage outmsg, Client c)
|
||||
{
|
||||
c.ChatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, c.LastRecvChatMsgID));
|
||||
for (int i = 0; i < c.ChatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++)
|
||||
@@ -2024,7 +2032,7 @@ namespace Barotrauma.Networking
|
||||
//not enough room in this packet
|
||||
return;
|
||||
}
|
||||
c.ChatMsgQueue[i].ServerWrite(outmsg, c);
|
||||
c.ChatMsgQueue[i].ServerWrite(segmentTable, outmsg, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3327,9 +3335,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.UPDATE_LOBBY);
|
||||
msg.WriteByte((byte)ServerNetObject.VOTE);
|
||||
Voting.ServerWrite(msg);
|
||||
msg.WriteByte((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
using (var segmentTable = SegmentTableWriter<ServerNetSegment>.StartWriting(msg))
|
||||
{
|
||||
segmentTable.StartNewSegment(ServerNetSegment.Vote);
|
||||
Voting.ServerWrite(msg);
|
||||
}
|
||||
|
||||
foreach (var c in recipients)
|
||||
{
|
||||
|
||||
+9
-9
@@ -123,7 +123,7 @@ namespace Barotrauma.Networking
|
||||
//remove old events that have been sent to all clients, they are redundant now
|
||||
// keep at least one event in the list (lastSentToAll == e.ID) so we can use it to keep track of the latest ID
|
||||
// and events less than 15 seconds old to give disconnected clients a bit of time to reconnect without getting desynced
|
||||
if (Timing.TotalTime > GameMain.GameSession.RoundStartTime + NetConfig.RoundStartSyncDuration)
|
||||
if (GameMain.GameSession.RoundDuration > NetConfig.RoundStartSyncDuration)
|
||||
{
|
||||
events.RemoveAll(e =>
|
||||
(NetIdUtils.IdMoreRecent(lastSentToAll, e.ID) || !inGameClientsPresent) &&
|
||||
@@ -217,7 +217,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (Timing.TotalTime - lastWarningTime > 5.0 &&
|
||||
Timing.TotalTime - lastSentToAnyoneTime > 10.0 &&
|
||||
Timing.TotalTime > GameMain.GameSession.RoundStartTime + NetConfig.RoundStartSyncDuration)
|
||||
GameMain.GameSession.RoundDuration > NetConfig.RoundStartSyncDuration)
|
||||
{
|
||||
lastWarningTime = Timing.TotalTime;
|
||||
GameServer.Log("WARNING: ServerEntityEventManager is lagging behind! Last sent id: " + lastSentToAnyone.ToString() + ", latest create id: " + ID.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
@@ -229,7 +229,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
ServerEntityEvent firstEventToResend = events.Find(e => e.ID == (ushort)(lastSentToAll + 1));
|
||||
if (firstEventToResend != null &&
|
||||
Timing.TotalTime > GameMain.GameSession.RoundStartTime + NetConfig.RoundStartSyncDuration &&
|
||||
GameMain.GameSession.RoundDuration > NetConfig.RoundStartSyncDuration &&
|
||||
((lastSentToAnyoneTime - firstEventToResend.CreateTime) > NetConfig.OldReceivedEventKickTime || (Timing.TotalTime - firstEventToResend.CreateTime) > NetConfig.OldEventKickTime))
|
||||
{
|
||||
// This event is 10 seconds older than the last one we've successfully sent,
|
||||
@@ -295,15 +295,15 @@ namespace Barotrauma.Networking
|
||||
/// <summary>
|
||||
/// Writes all the events that the client hasn't received yet into the outgoing message
|
||||
/// </summary>
|
||||
public void Write(Client client, IWriteMessage msg)
|
||||
public void Write(in SegmentTableWriter<ServerNetSegment> segmentTable, Client client, IWriteMessage msg)
|
||||
{
|
||||
Write(client, msg, out _);
|
||||
Write(segmentTable, client, msg, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes all the events that the client hasn't received yet into the outgoing message
|
||||
/// </summary>
|
||||
public void Write(Client client, IWriteMessage msg, out List<NetEntityEvent> sentEvents)
|
||||
public void Write(in SegmentTableWriter<ServerNetSegment> segmentTable, Client client, IWriteMessage msg, out List<NetEntityEvent> sentEvents)
|
||||
{
|
||||
List<NetEntityEvent> eventsToSync = GetEventsToSync(client);
|
||||
|
||||
@@ -315,7 +315,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
//too many events for one packet
|
||||
//(normal right after a round has just started, don't show a warning if it's been less than 10 seconds)
|
||||
if (eventsToSync.Count > 200 && GameMain.GameSession != null && Timing.TotalTime > GameMain.GameSession.RoundStartTime + 10.0)
|
||||
if (eventsToSync.Count > 200 && GameMain.GameSession != null && GameMain.GameSession.RoundDuration > 10.0)
|
||||
{
|
||||
if (eventsToSync.Count > 200 && !client.NeedsMidRoundSync && Timing.TotalTime > lastEventCountHighWarning + 2.0)
|
||||
{
|
||||
@@ -345,7 +345,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (client.NeedsMidRoundSync)
|
||||
{
|
||||
msg.WriteByte((byte)ServerNetObject.ENTITY_EVENT_INITIAL);
|
||||
segmentTable.StartNewSegment(ServerNetSegment.EntityEventInitial);
|
||||
msg.WriteUInt16(client.UnreceivedEntityEventCount);
|
||||
msg.WriteUInt16(client.FirstNewEventID);
|
||||
|
||||
@@ -353,7 +353,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.WriteByte((byte)ServerNetObject.ENTITY_EVENT);
|
||||
segmentTable.StartNewSegment(ServerNetSegment.EntityEvent);
|
||||
Write(msg, eventsToSync, out sentEvents, client);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using Barotrauma.Steam;
|
||||
using Barotrauma.Steam;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class OrderChatMessage : ChatMessage
|
||||
{
|
||||
public override void ServerWrite(IWriteMessage msg, Client c)
|
||||
public override void ServerWrite(in SegmentTableWriter<ServerNetSegment> segmentTable, IWriteMessage msg, Client c)
|
||||
{
|
||||
msg.WriteByte((byte)ServerNetObject.CHAT_MESSAGE);
|
||||
segmentTable.StartNewSegment(ServerNetSegment.ChatMessage);
|
||||
msg.WriteUInt16(NetStateID);
|
||||
msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
msg.WriteString(SenderName);
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsRespawnPromptPendingForClient(Client c)
|
||||
private static bool IsRespawnPromptPendingForClient(Client c)
|
||||
{
|
||||
if (!UseRespawnPrompt || !(GameMain.GameSession.GameMode is MultiPlayerCampaign campaign)) { return false; }
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Barotrauma.Networking
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<CharacterInfo> GetBotsToRespawn()
|
||||
private static List<CharacterInfo> GetBotsToRespawn()
|
||||
{
|
||||
if (GameMain.Server.ServerSettings.BotSpawnMode == BotSpawnMode.Normal)
|
||||
{
|
||||
@@ -110,7 +110,7 @@ namespace Barotrauma.Networking
|
||||
return ShouldStartRespawnCountdown(characterToRespawnCount);
|
||||
}
|
||||
|
||||
private int GetMinCharactersToRespawn()
|
||||
private static int GetMinCharactersToRespawn()
|
||||
{
|
||||
return Math.Max((int)(GameMain.Server.ConnectedClients.Count * GameMain.Server.ServerSettings.MinRespawnRatio), 1);
|
||||
}
|
||||
@@ -464,7 +464,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (!(GameMain.GameSession.GameMode is CampaignMode))
|
||||
if (GameMain.GameSession.GameMode is not CampaignMode)
|
||||
{
|
||||
if (scooterPrefab != null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user