UpdateIdentityAck

This commit is contained in:
mischa 2024-07-20 15:28:32 +02:00
parent 2a72b12cea
commit b6e4e595dd
4 changed files with 74 additions and 2 deletions

View File

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine;
namespace Mirror namespace Mirror
{ {
@ -71,5 +72,30 @@ internal static void TrackIdentityAtTick(
// add the netid to the hashset // add the netid to the hashset
netIds.Add(netId); netIds.Add(netId);
} }
// when receiving an ack from a connection, update latest ack for
// all networkidentities that were in the acked batch.
internal static void UpdateIdentityAcks(
double timestamp,
SortedList<double, HashSet<uint>> identityTicks,
Dictionary<uint, double> identityAcks)
{
// find the identities that were in the acked batch
if (!identityTicks.TryGetValue(timestamp, out HashSet<uint> identities))
{
// for now, at least log a message so we know this happened.
Debug.Log($"UpdateLatestAck: batch @ {timestamp} was not in history anymore. This can happen if the other end was too far behind.");
return;
}
// update latest acks for all identities that were in the batch
foreach (uint netId in identities)
{
// unreliable messages may arrive out of order.
// only update if newer.
if (!identityAcks.TryGetValue(netId, out double ackTimestamp) || timestamp > ackTimestamp)
identityAcks[netId] = timestamp;
}
}
} }
} }

View File

@ -70,7 +70,7 @@ public abstract class NetworkConnection
// currently we sync one entity at a time in batches, so we also need to store acks for one at a time. // currently we sync one entity at a time in batches, so we also need to store acks for one at a time.
// <netId, timestamp> // <netId, timestamp>
// TODO remove old when unspawned // TODO remove old when unspawned
readonly Dictionary<uint, double> identityAcks = new Dictionary<uint, double>(); internal readonly Dictionary<uint, double> identityAcks = new Dictionary<uint, double>();
// //

View File

@ -497,7 +497,10 @@ static void OnTimeSnapshotMessage(NetworkConnectionToClient connection, TimeSnap
// ack delta compression /////////////////////////////////////////////// // ack delta compression ///////////////////////////////////////////////
static void OnAckMessage(NetworkConnectionToClient connection, AckMessage message) static void OnAckMessage(NetworkConnectionToClient connection, AckMessage message)
{ {
Debug.Log($"NetworkServer received acknowledgement: {message.batchTimestamp} for connId={connection.connectionId}"); // for the acknowledged batch's timestamp:
// update last ack for all NetworkIdentities that were in the batch.
// Debug.Log($"NetworkServer received acknowledgement: {message.batchTimestamp} for connId={connection.connectionId}");
AckDeltaCompression.UpdateIdentityAcks(message.batchTimestamp, connection.identityTicks, connection.identityAcks);
} }
// connections ///////////////////////////////////////////////////////// // connections /////////////////////////////////////////////////////////

View File

@ -90,5 +90,48 @@ public void TrackIdentityAtTick()
Assert.That(identityTicks[4.0].Contains(1337)); Assert.That(identityTicks[4.0].Contains(1337));
Assert.That(identityTicks[4.0].Contains(101)); Assert.That(identityTicks[4.0].Contains(101));
} }
[Test]
public void UpdateIdentityAcks()
{
// prepare a few batches that were sent, with NetworkIdentities included
SortedList<double, HashSet<uint>> identityTicks = new SortedList<double, HashSet<uint>>();
int MaxCount = 3;
// insert t = 1 with a few netids
AckDeltaCompression.TrackIdentityAtTick(1.0, 42, identityTicks, MaxCount);
AckDeltaCompression.TrackIdentityAtTick(1.0, 1337, identityTicks, MaxCount);
// insert t = 2 with a the same netIds and one new
AckDeltaCompression.TrackIdentityAtTick(2.0, 42, identityTicks, MaxCount);
AckDeltaCompression.TrackIdentityAtTick(2.0, 1337, identityTicks, MaxCount);
AckDeltaCompression.TrackIdentityAtTick(2.0, 101, identityTicks, MaxCount);
// insert t = 3 without one of the previous netIds
AckDeltaCompression.TrackIdentityAtTick(3.0, 1337, identityTicks, MaxCount);
AckDeltaCompression.TrackIdentityAtTick(3.0, 101, identityTicks, MaxCount);
// remote acks t = 1: 42, 1337
Dictionary<uint, double> identityAcks = new Dictionary<uint, double>();
AckDeltaCompression.UpdateIdentityAcks(1.0, identityTicks, identityAcks);
Assert.That(identityAcks.Count, Is.EqualTo(2));
Assert.That(identityAcks[42], Is.EqualTo(1.0));
Assert.That(identityAcks[1337], Is.EqualTo(1.0));
// remote acks t = 3 before t = 2: 1337, 101
AckDeltaCompression.UpdateIdentityAcks(3.0, identityTicks, identityAcks);
Assert.That(identityAcks.Count, Is.EqualTo(3));
Assert.That(identityAcks[42], Is.EqualTo(1.0)); // still from the first ack
Assert.That(identityAcks[1337], Is.EqualTo(3.0)); // acked
Assert.That(identityAcks[101], Is.EqualTo(3.0)); // acked
// remote acks t = 2: 42, 1337, 101.
// only 42 is should be updated since 1337 and 101 are already newer
AckDeltaCompression.UpdateIdentityAcks(2.0, identityTicks, identityAcks);
Assert.That(identityAcks.Count, Is.EqualTo(3));
Assert.That(identityAcks[42], Is.EqualTo(2.0)); // updated
Assert.That(identityAcks[1337], Is.EqualTo(3.0)); // already newer
Assert.That(identityAcks[101], Is.EqualTo(3.0)); // already newer
}
} }
} }