-
Notifications
You must be signed in to change notification settings - Fork 450
feat: snapshot. MTT-1088 Snapshot acknowledgment gaps #1083
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
94313c7
daa7477
9cb59e4
62e87d5
64bb7ec
847adcd
bc49244
4963d9c
10ed439
9674acc
bc4805d
5c9a703
411ef16
8201cd2
7a597b3
d2318bc
9f81229
d0b6617
43c26f6
4e32df9
4222365
2bf493d
16d3db1
d421c64
d891f1e
7c55e4e
140a9e7
775eb83
8494c4d
767d9eb
ce3bb6f
0c7a8b1
1cd9af7
0c0b298
f8df5c7
121646f
1049f53
06284f5
1c17469
2bc5ae1
60c1cc0
cb38fd9
948f4fa
75ba255
564dc26
f79b182
3077c38
1984155
e659949
192bcc3
e79efce
f8bddd1
d44337d
081df43
2c8fbbc
2aeff8f
7599ac0
a66108d
edadc75
21fca5c
1caaca3
cf6b615
4c48ced
5015050
dc9dfbc
2fa6f59
489d592
8b42189
802703a
dd4eb5e
051caec
975a52a
6d1d2e7
1a8a5cf
f5768a2
b0d9e5e
3c905a8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -472,10 +472,30 @@ internal void ReadSpawns(NetworkReader reader) | |
} | ||
} | ||
|
||
internal ushort ReadAcks(ulong clientId, ClientData clientData, NetworkReader reader) | ||
internal void ReadAcks(ulong clientId, ClientData clientData, NetworkReader reader, ConnectionRtt connection) | ||
{ | ||
ushort ackSequence = reader.ReadUInt16(); | ||
ushort seqMask = reader.ReadUInt16(); | ||
|
||
// process the latest acknowledgment | ||
ProcessSingleAck(ackSequence, clientId, clientData, connection); | ||
|
||
// for each bit in the mask, acknowledge one message before | ||
while (seqMask != 0) | ||
{ | ||
ackSequence--; | ||
// extract least bit | ||
if (seqMask % 2 == 1) | ||
{ | ||
ProcessSingleAck(ackSequence, clientId, clientData, connection); | ||
} | ||
// move to next bit | ||
seqMask >>= 1; | ||
} | ||
} | ||
|
||
internal void ProcessSingleAck(ushort ackSequence, ulong clientId, ClientData clientData, ConnectionRtt connection) | ||
{ | ||
// look through the spawns sent | ||
foreach (var sent in clientData.SentSpawns) | ||
{ | ||
|
@@ -529,7 +549,8 @@ internal ushort ReadAcks(ulong clientId, ClientData clientData, NetworkReader re | |
} | ||
} | ||
|
||
return ackSequence; | ||
// keep track of RTTs, using the sequence number acknowledgement as a marker | ||
connection.NotifyAck(ackSequence, Time.unscaledTime); | ||
} | ||
|
||
/// <summary> | ||
|
@@ -564,6 +585,7 @@ internal struct SentSpawn // this struct also stores Despawns, not just Spawns | |
|
||
internal ushort SequenceNumber = 0; // the next sequence number to use for this client | ||
internal ushort LastReceivedSequence = 0; // the last sequence number received by this client | ||
internal ushort ReceivedSequenceMask = 0; // bitmask of the messages before the last one that we received. | ||
|
||
internal int NextSpawnIndex = 0; // index of the last spawn sent. Used to cycle through spawns (LRU scheme) | ||
internal int NextDespawnIndex = 0; // same as above, but for despawns. | ||
|
@@ -686,8 +708,6 @@ private void SendSnapshot(ulong clientId) | |
|
||
m_ConnectionRtts[clientId].NotifySend(m_ClientData[clientId].SequenceNumber, Time.unscaledTime); | ||
|
||
// Send the entry index and the buffer where the variables are serialized | ||
|
||
var context = m_NetworkManager.MessageQueueContainer.EnterInternalCommandContext( | ||
MessageQueueContainer.MessageType.SnapshotData, NetworkChannel.SnapshotExchange, | ||
new[] { clientId }, NetworkUpdateLoop.UpdateStage); | ||
|
@@ -698,20 +718,27 @@ private void SendSnapshot(ulong clientId) | |
{ | ||
var sequence = m_ClientData[clientId].SequenceNumber; | ||
|
||
// write the tick and sequence header | ||
nonNullContext.NetworkWriter.WriteInt32Packed(m_CurrentTick); | ||
nonNullContext.NetworkWriter.WriteUInt16(sequence); | ||
|
||
var buffer = (NetworkBuffer)nonNullContext.NetworkWriter.GetStream(); | ||
|
||
using (var writer = PooledNetworkWriter.Get(buffer)) | ||
{ | ||
// write the snapshot: buffer, index, spawns, despawns | ||
writer.WriteUInt16(SentinelBefore); | ||
WriteBuffer(buffer); | ||
WriteIndex(buffer); | ||
WriteSpawns(buffer, clientId); | ||
WriteAcks(buffer, clientId); | ||
writer.WriteUInt16(SentinelAfter); | ||
|
||
m_ClientData[clientId].LastReceivedSequence = 0; | ||
|
||
// todo: this is incorrect (well, sub-optimal) | ||
// we should still continue ack'ing past messages, in case this one is dropped | ||
m_ClientData[clientId].ReceivedSequenceMask = 0; | ||
m_ClientData[clientId].SequenceNumber++; | ||
} | ||
} | ||
|
@@ -806,7 +833,9 @@ private void WriteAcks(NetworkBuffer buffer, ulong clientId) | |
{ | ||
using (var writer = PooledNetworkWriter.Get(buffer)) | ||
{ | ||
// todo: revisit whether 16-bit is enough for LastReceivedSequence | ||
writer.WriteUInt16(m_ClientData[clientId].LastReceivedSequence); | ||
writer.WriteUInt16(m_ClientData[clientId].ReceivedSequenceMask); | ||
} | ||
} | ||
|
||
|
@@ -911,12 +940,6 @@ private void WriteVariableToSnapshot(Snapshot snapshot, INetworkVariable network | |
/// <param name="snapshotStream">The stream to read from</param> | ||
internal void ReadSnapshot(ulong clientId, Stream snapshotStream) | ||
{ | ||
// poor man packet loss simulation | ||
//if (Random.Range(0, 10) > 5) | ||
//{ | ||
// return; | ||
//} | ||
|
||
// todo: temporary hack around bug | ||
if (!m_NetworkManager.IsServer) | ||
{ | ||
|
@@ -937,6 +960,23 @@ internal void ReadSnapshot(ulong clientId, Stream snapshotStream) | |
var sequence = reader.ReadUInt16(); | ||
|
||
// todo: check we didn't miss any and deal with gaps | ||
|
||
if (m_ClientData[clientId].ReceivedSequenceMask != 0) | ||
{ | ||
// since each bit in ReceivedSequenceMask is relative to the last received sequence | ||
// we need to shift all the bits by the difference in sequence | ||
m_ClientData[clientId].ReceivedSequenceMask <<= | ||
(sequence - m_ClientData[clientId].LastReceivedSequence); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to to bounds checking on |
||
} | ||
|
||
if (m_ClientData[clientId].LastReceivedSequence != 0) | ||
{ | ||
// because the bit we're adding for the previous ReceivedSequenceMask | ||
// was implicit, it needs to be shift by one less | ||
m_ClientData[clientId].ReceivedSequenceMask += | ||
(ushort)(1 << (ushort)((sequence - 1) - m_ClientData[clientId].LastReceivedSequence)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same check here on under / overflow? |
||
} | ||
|
||
m_ClientData[clientId].LastReceivedSequence = sequence; | ||
|
||
var sentinel = reader.ReadUInt16(); | ||
|
@@ -948,10 +988,7 @@ internal void ReadSnapshot(ulong clientId, Stream snapshotStream) | |
m_Snapshot.ReadBuffer(reader, snapshotStream); | ||
m_Snapshot.ReadIndex(reader); | ||
m_Snapshot.ReadSpawns(reader); | ||
var ackSequence = m_Snapshot.ReadAcks(clientId, m_ClientData[clientId], reader); | ||
|
||
// keep track of RTTs, using the sequence number acknowledgement as a marker | ||
GetConnectionRtt(clientId).NotifyAck(ackSequence, Time.unscaledTime); | ||
m_Snapshot.ReadAcks(clientId, m_ClientData[clientId], reader, GetConnectionRtt(clientId)); | ||
|
||
sentinel = reader.ReadUInt16(); | ||
if (sentinel != SentinelAfter) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have to remember to port this over to @ShadauxCat's new scheme