Some handling of dropped packages

This commit is contained in:
2026-01-04 19:06:03 +01:00
parent 60abba8498
commit 2636e65e4d
4 changed files with 1240 additions and 1040 deletions

View File

@@ -245,7 +245,7 @@ namespace Marro.PacManUdon
}
}
private void HandleError()
private void HandleError(bool clearBuffer)
{
retriesWithoutSuccess++;
@@ -259,7 +259,12 @@ namespace Marro.PacManUdon
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Encountered data error, attempting to recover via full sync.");
ClearBuffer();
if (clearBuffer)
{
ClearBuffer();
}
isSynced = false;
if (!isOwner)
{
@@ -293,16 +298,7 @@ namespace Marro.PacManUdon
var timestamp = TimeToTimestamp(SyncedTime);
if (timestamp != lastEventTimestamp)
{
lastEventId = 0;
}
else
{
lastEventId++;
}
var eventId = lastEventId;
var eventId = GetNextEventId(lastEventId);
InitializeEvent(eventType, timestamp, eventId, BufferMaxSizeBytes, out byte[][] data, out var index);
@@ -334,6 +330,9 @@ namespace Marro.PacManUdon
RequestSerialization();
lastEventTimestamp = timestamp;
lastEventId = eventId;
retriesWithoutSuccess = 0; // We had success!
}
@@ -354,6 +353,12 @@ namespace Marro.PacManUdon
data[0] = header;
index = 1;
}
[NetworkCallable]
public void RequestEventReceived(NetworkEventType eventType)
{
SendEvent(eventType);
}
#endregion
#region Receiver
@@ -368,56 +373,78 @@ namespace Marro.PacManUdon
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.Owner, "RequestEventReceived", eventType);
}
private void ProcessIncomingData()
private void StoreIncomingData()
{
if (networkedData.Length == 0)
{
return; // Nothing to process
return; // Nothing to store
}
Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received {networkedData.Length} bytes!\nBytes received:\n{BytesToString(networkedData)}");
var length = networkedData.Length;
int index = 0;
while (index < length)
int eventSize = 0; // Store event size here so we can increment the index no matter how we increment the loop
while (true)
{
index += eventSize;
if (index >= length)
{
break;
}
if (length - index < HeaderLength)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(ProcessIncomingData)}: Remaining data in networkedData is not long enough to form a complete event!");
HandleError();
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(StoreIncomingData)}: Remaining data in networkedData is not long enough to form a complete event! remaining: {length - index}.");
HandleError(false);
return;
}
eventSize = networkedData[index + HeaderEventSizeIndex];
if (length - index < eventSize)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(StoreIncomingData)}: Event size is larger than total remaining data! {nameof(eventSize)}: {eventSize}, remaining: {length - index}.");
HandleError(false);
return;
}
var eventSize = networkedData[index + HeaderEventSizeIndex];
var eventType = (NetworkEventType)networkedData[index + HeaderEventTypeIndex];
if (eventType == NetworkEventType.FullSync)
{
ProcessIncomingFullSync(index, eventSize); // Immediately process full sync
index += eventSize;
continue;
}
if (!isSynced)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received event of type {eventType} while we are not yet synced to the remote time, ignoring event.");
index += eventSize;
continue;
}
var timestamp = networkedData[index + HeaderTimestampIndex];
var messageId = networkedData[index + HeaderEventIdIndex];
var eventId = networkedData[index + HeaderEventIdIndex];
if (timestamp == lastEventTimestamp
&& messageId == lastEventId)
&& eventId == lastEventId)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Duplicate message of type {eventType}, timestamp: {timestamp}, messageId: {messageId}.");
index += eventSize;
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Duplicate message of type {eventType}, timestamp: {timestamp}, messageId: {eventId}.");
continue;
}
if (eventId != GetNextEventId(lastEventId))
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) EventIds were not sequential! Did we miss a serialization? Timestamp: {timestamp}, eventId: {eventId}, lastEventId: {lastEventId}.");
HandleError(false);
return;
}
AppendEventToBuffer(index, eventSize);
index += eventSize;
lastEventTimestamp = timestamp;
lastEventId = eventId;
}
}
@@ -472,14 +499,14 @@ namespace Marro.PacManUdon
if (!success)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Malformed data reported by {obj.name} during event type {eventType}!");
HandleError();
HandleError(true);
return;
}
if (index > this.bufferIndex)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer overflow during {nameof(SyncedObject.SetSyncedData)} for {obj.name} in event type {eventType}!");
HandleError();
HandleError(true);
return;
}
}
@@ -488,7 +515,7 @@ namespace Marro.PacManUdon
if (index != eventSize)
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Amount of data read does not match event size! Expected {eventSize}, read {index}.");
HandleError();
HandleError(true);
return;
}
@@ -558,7 +585,7 @@ namespace Marro.PacManUdon
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Too much data in buffer to store event!");
}
HandleError(); // We can store event now that we cleared the buffer.
HandleError(false);
return false;
}
@@ -621,7 +648,7 @@ namespace Marro.PacManUdon
else
{
Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) New event is earlier than previous event!");
HandleError();
HandleError(true);
return;
}
}
@@ -637,15 +664,24 @@ namespace Marro.PacManUdon
}
#endregion
#region Header
public static byte GetNextEventId(byte currentEventId)
{
if (currentEventId == byte.MaxValue) // Udon forces overflow checks
{
return 0;
}
currentEventId += 1;
return currentEventId;
}
#endregion
#region VRC events
public override void OnOwnershipTransferred(VRCPlayerApi newOwner)
{
SetOwner(newOwner == Networking.LocalPlayer);
if(isOwner)
{
HandleError();
}
}
public override void OnPreSerialization()
@@ -685,7 +721,7 @@ namespace Marro.PacManUdon
{
if (!isOwner)
{
ProcessIncomingData();
StoreIncomingData();
}
}
#endregion