Changed lobby & chatMsg IDs to from uint to ushort, added a utility class that handles the wrap around of IDs

This commit is contained in:
Regalis
2017-02-05 22:55:19 +02:00
parent 9bda79036a
commit 4b8d1054b1
7 changed files with 94 additions and 42 deletions

View File

@@ -163,6 +163,7 @@
<Compile Include="Source\Networking\NetEntityEvent\NetEntityEventManager.cs" />
<Compile Include="Source\Networking\NetEntityEvent\ServerEntityEventManager.cs" />
<Compile Include="Source\Networking\NetStats.cs" />
<Compile Include="Source\Networking\NetIdUtils.cs" />
<Compile Include="Source\Networking\RespawnManager.cs" />
<Compile Include="Source\Networking\ServerLog.cs" />
<Compile Include="Source\Networking\WhiteList.cs" />

View File

@@ -47,9 +47,9 @@ namespace Barotrauma.Networking
private set;
}
public static UInt32 LastID = 0;
public static UInt16 LastID = 0;
public UInt32 NetStateID
public UInt16 NetStateID
{
get;
set;
@@ -138,9 +138,9 @@ namespace Barotrauma.Networking
static public void ServerRead(NetIncomingMessage msg, Client c)
{
UInt32 ID = msg.ReadUInt32();
UInt16 ID = msg.ReadUInt16();
string txt = msg.ReadString();
if (c.lastSentChatMsgID < ID)
if (NetIdUtils.IdMoreRecent(ID, c.lastSentChatMsgID))
{
//this chat message is new to the server
GameMain.Server.SendChatMessage(txt, null, c);
@@ -169,7 +169,7 @@ namespace Barotrauma.Networking
static public void ClientRead(NetIncomingMessage msg)
{
UInt32 ID = msg.ReadUInt32();
UInt16 ID = msg.ReadUInt16();
ChatMessageType type = (ChatMessageType)msg.ReadByte();
string txt = msg.ReadString();
@@ -189,7 +189,7 @@ namespace Barotrauma.Networking
senderName = msg.ReadString();
}
if (ID > LastID)
if (NetIdUtils.IdMoreRecent(ID, LastID))
{
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter);
LastID = ID;

View File

@@ -30,11 +30,11 @@ namespace Barotrauma.Networking
public NetConnection Connection { get; set; }
public string version;
public bool inGame;
public UInt32 lastRecvGeneralUpdate = 0;
public UInt16 lastRecvGeneralUpdate = 0;
public bool hasLobbyData = false;
public UInt32 lastSentChatMsgID = 0; //last msg this client said
public UInt32 lastRecvChatMsgID = 0; //last msg this client knows about
public UInt16 lastSentChatMsgID = 0; //last msg this client said
public UInt16 lastRecvChatMsgID = 0; //last msg this client knows about
public UInt32 lastSentEntityEventID = 0;
public UInt32 lastRecvEntityEventID = 0;
@@ -42,7 +42,7 @@ namespace Barotrauma.Networking
public UInt32 lastRecvEntitySpawnID = 0;
public List<ChatMessage> chatMsgQueue = new List<ChatMessage>();
public UInt32 lastChatMsgQueueID;
public UInt16 lastChatMsgQueueID;
public float ChatSpamSpeed;
public float ChatSpamTimer;
public int ChatSpamCount;

View File

@@ -35,8 +35,8 @@ namespace Barotrauma.Networking
private int nonce;
private string saltedPw;
private UInt32 lastSentChatMsgID = 0; //last message this client has successfully sent
private UInt32 lastQueueChatMsgID = 0; //last message added to the queue
private UInt16 lastSentChatMsgID = 0; //last message this client has successfully sent
private UInt16 lastQueueChatMsgID = 0; //last message added to the queue
private List<ChatMessage> chatMsgQueue = new List<ChatMessage>();
public UInt32 LastSentEntityEventID;
@@ -729,13 +729,13 @@ namespace Barotrauma.Networking
if (lobbyUpdated)
{
UInt32 updateID = inc.ReadUInt32();
UInt16 updateID = inc.ReadUInt16();
string serverName = inc.ReadString();
string serverText = inc.ReadString();
if (inc.ReadBoolean())
{
ReadInitialUpdate(inc, updateID <= GameMain.NetLobbyScreen.LastUpdateID);
ReadInitialUpdate(inc, !NetIdUtils.IdMoreRecent(updateID,GameMain.NetLobbyScreen.LastUpdateID));
}
string selectSubName = inc.ReadString();
@@ -768,7 +768,7 @@ namespace Barotrauma.Networking
}
//ignore the message if we already a more up-to-date one
if (updateID > GameMain.NetLobbyScreen.LastUpdateID)
if (NetIdUtils.IdMoreRecent(updateID, GameMain.NetLobbyScreen.LastUpdateID))
{
GameMain.NetLobbyScreen.LastUpdateID = updateID;
@@ -811,7 +811,7 @@ namespace Barotrauma.Networking
Voting.AllowModeVoting = allowModeVoting;
}
}
lastSentChatMsgID = inc.ReadUInt32();
lastSentChatMsgID = inc.ReadUInt16();
break;
case ServerNetObject.CHAT_MESSAGE:
ChatMessage.ClientRead(inc);
@@ -833,7 +833,7 @@ namespace Barotrauma.Networking
switch (objHeader)
{
case ServerNetObject.SYNC_IDS:
lastSentChatMsgID = inc.ReadUInt32();
lastSentChatMsgID = inc.ReadUInt16();
LastSentEntityEventID = inc.ReadUInt32();
break;
case ServerNetObject.ENTITY_POSITION:
@@ -878,11 +878,8 @@ namespace Barotrauma.Networking
outmsg.Write((byte)ClientNetObject.SYNC_IDS);
outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID);
outmsg.Write(ChatMessage.LastID);
ChatMessage removeMsg;
while ((removeMsg=chatMsgQueue.Find(cMsg => cMsg.NetStateID <= lastSentChatMsgID)) != null)
{
chatMsgQueue.Remove(removeMsg);
}
chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, lastSentChatMsgID));
foreach (ChatMessage cMsg in chatMsgQueue)
{
@@ -903,11 +900,7 @@ namespace Barotrauma.Networking
outmsg.Write(Entity.Spawner.NetStateID);
outmsg.Write(entityEventManager.LastReceivedID);
ChatMessage removeMsg;
while ((removeMsg = chatMsgQueue.Find(cMsg => cMsg.NetStateID <= lastSentChatMsgID)) != null)
{
chatMsgQueue.Remove(removeMsg);
}
chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, lastSentChatMsgID));
foreach (ChatMessage cMsg in chatMsgQueue)
{

View File

@@ -66,7 +66,7 @@ namespace Barotrauma.Networking
{
this.password = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password)));
}
config = new NetPeerConfiguration("barotrauma");
netStats = new NetStats();
@@ -78,6 +78,8 @@ namespace Barotrauma.Networking
config.SimulatedMinimumLatency = 0.1f;
config.ConnectionTimeout = 60.0f;
NetIdUtils.Test();
#endif
config.Port = port;
Port = port;
@@ -622,8 +624,8 @@ namespace Barotrauma.Networking
{
case ClientNetObject.SYNC_IDS:
//TODO: might want to use a clever class for this
c.lastRecvGeneralUpdate = Math.Min(Math.Max(c.lastRecvGeneralUpdate, inc.ReadUInt32()), GameMain.NetLobbyScreen.LastUpdateID);
c.lastRecvChatMsgID = Math.Min(Math.Max(c.lastRecvChatMsgID, inc.ReadUInt32()), c.lastChatMsgQueueID);
c.lastRecvGeneralUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.lastRecvGeneralUpdate, GameMain.NetLobbyScreen.LastUpdateID);
c.lastRecvChatMsgID = NetIdUtils.Clamp(inc.ReadUInt16(), c.lastRecvChatMsgID, c.lastChatMsgQueueID);
break;
case ClientNetObject.CHAT_MESSAGE:
ChatMessage.ServerRead(inc, c);
@@ -657,7 +659,7 @@ namespace Barotrauma.Networking
case ClientNetObject.SYNC_IDS:
//TODO: might want to use a clever class for this
UInt32 lastRecvChatMsgID = inc.ReadUInt32();
UInt16 lastRecvChatMsgID = inc.ReadUInt16();
UInt32 lastRecvEntitySpawnID = inc.ReadUInt32();
UInt32 lastRecvEntityEventID = inc.ReadUInt32();
@@ -734,7 +736,7 @@ namespace Barotrauma.Networking
outmsg.Write(c.lastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
outmsg.Write(c.lastSentEntityEventID);
c.chatMsgQueue.RemoveAll(cMsg => cMsg.NetStateID <= c.lastRecvChatMsgID);
c.chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, c.lastRecvChatMsgID));
foreach (ChatMessage cMsg in c.chatMsgQueue)
{
cMsg.ServerWrite(outmsg, c);
@@ -797,8 +799,8 @@ namespace Barotrauma.Networking
outmsg.Write((byte)ServerPacketHeader.UPDATE_LOBBY);
outmsg.Write((byte)ServerNetObject.SYNC_IDS);
if (c.lastRecvGeneralUpdate<GameMain.NetLobbyScreen.LastUpdateID)
if (NetIdUtils.IdMoreRecent(GameMain.NetLobbyScreen.LastUpdateID, c.lastRecvGeneralUpdate))
{
outmsg.Write(true);
outmsg.WritePadBits();
@@ -849,7 +851,7 @@ namespace Barotrauma.Networking
outmsg.Write(c.lastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
c.chatMsgQueue.RemoveAll(cMsg => cMsg.NetStateID <= c.lastRecvChatMsgID);
c.chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, c.lastRecvChatMsgID));
foreach (ChatMessage cMsg in c.chatMsgQueue)
{
cMsg.ServerWrite(outmsg, c);
@@ -1480,10 +1482,10 @@ namespace Barotrauma.Networking
modifiedMessage,
(ChatMessageType)type,
senderCharacter);
chatMsg.NetStateID = client.chatMsgQueue.Count > 0 ?
client.chatMsgQueue.Last().NetStateID + 1 :
client.lastRecvChatMsgID+1;
chatMsg.NetStateID = client.chatMsgQueue.Count > 0 ?
(ushort)(client.chatMsgQueue.Last().NetStateID + 1) :
(ushort)(client.lastRecvChatMsgID + 1);
client.chatMsgQueue.Add(chatMsg);
client.lastChatMsgQueueID = chatMsg.NetStateID;

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Barotrauma.Networking
{
static class NetIdUtils
{
/// <summary>
/// Is newID more recent than oldID
/// </summary>
public static bool IdMoreRecent(ushort newID, ushort oldID)
{
uint id1 = newID;
uint id2 = oldID;
return
(id1 > id2) && (id1 - id2 <= ushort.MaxValue / 2)
||
(id2 > id1) && (id2 - id1 > ushort.MaxValue / 2);
}
public static ushort Clamp(ushort id, ushort min, ushort max)
{
if (IdMoreRecent(min, max))
{
throw new ArgumentException("Min cannot be larger than max");
}
if (!IdMoreRecent(id, min))
{
return min;
}
else if (IdMoreRecent(id, max))
{
return max;
}
return id;
}
#if DEBUG
public static void Test()
{
Debug.Assert(NetIdUtils.IdMoreRecent((ushort)2, (ushort)1));
Debug.Assert(NetIdUtils.IdMoreRecent((ushort)2, (ushort)(ushort.MaxValue - 5)));
Debug.Assert(!NetIdUtils.IdMoreRecent((ushort)ushort.MaxValue, (ushort)5));
Debug.Assert(Clamp((ushort)5, (ushort)1, (ushort)10) == 5);
Debug.Assert(Clamp((ushort)(ushort.MaxValue - 5), (ushort)(ushort.MaxValue - 2), (ushort)3) == (ushort)(ushort.MaxValue - 2));
}
#endif
}
}

View File

@@ -52,9 +52,8 @@ namespace Barotrauma
public bool IsServer;
public string ServerName;
const float NetworkUpdateInterval = 1.0f;
private UInt32 lastUpdateID;
public UInt32 LastUpdateID
private UInt16 lastUpdateID;
public UInt16 LastUpdateID
{
get { if (GameMain.Server != null && lastUpdateID < 1) lastUpdateID++; return lastUpdateID; }
set { if (GameMain.Server != null) return; lastUpdateID = value; }