Skip to content

Commit e81e767

Browse files
committed
fix: Added scene buffering for scene switches
Fixes: #267
1 parent 3e0006d commit e81e767

File tree

3 files changed

+140
-13
lines changed

3 files changed

+140
-13
lines changed

MLAPI/Core/NetworkingManager.cs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ private void Init(bool server)
333333
NetworkSceneManager.sceneIndexToString.Clear();
334334
NetworkSceneManager.sceneNameToIndex.Clear();
335335
NetworkSceneManager.sceneSwitchProgresses.Clear();
336+
NetworkSceneManager.sceneBufferedNetworkIds.Clear();
336337

337338
if (NetworkConfig.NetworkTransport == null)
338339
{
@@ -865,7 +866,7 @@ private void HandleRawTransportPoll(NetEventType eventType, ulong clientId, stri
865866
}
866867
}
867868

868-
private void HandleIncomingData(ulong clientId, string channelName, ArraySegment<byte> data, float receiveTime)
869+
internal void HandleIncomingData(ulong clientId, string channelName, ArraySegment<byte> data, float receiveTime)
869870
{
870871
if (LogHelper.CurrentLogLevel <= LogLevel.Developer) LogHelper.LogInfo("Unwrapping Data Header");
871872

@@ -902,6 +903,27 @@ private void HandleIncomingData(ulong clientId, string channelName, ArraySegment
902903

903904
#region INTERNAL MESSAGE
904905

906+
void bufferCallback(ulong networkId)
907+
{
908+
// Alloc some memory
909+
PooledBitStream pooledData = PooledBitStream.Get();
910+
911+
// Copy the data
912+
pooledData.Write(data.Array, data.Offset, data.Count);
913+
914+
NetworkSceneManager.BufferedMessage message = new NetworkSceneManager.BufferedMessage()
915+
{
916+
channelName = channelName,
917+
pool = pooledData,
918+
payload = new ArraySegment<byte>(pooledData.GetBuffer(), 0, data.Count),
919+
receiveTime = receiveTime,
920+
sender = clientId
921+
};
922+
923+
NetworkSceneManager.sceneBufferedNetworkIds[networkId].Enqueue(message);
924+
}
925+
926+
905927
switch (messageType)
906928
{
907929
case MLAPIConstants.MLAPI_CONNECTION_REQUEST:
@@ -934,25 +956,25 @@ private void HandleIncomingData(ulong clientId, string channelName, ArraySegment
934956
if (IsClient) InternalMessageHandler.HandleTimeSync(clientId, messageStream, receiveTime);
935957
break;
936958
case MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA:
937-
InternalMessageHandler.HandleNetworkedVarDelta(clientId, messageStream);
959+
InternalMessageHandler.HandleNetworkedVarDelta(clientId, messageStream, bufferCallback);
938960
break;
939961
case MLAPIConstants.MLAPI_NETWORKED_VAR_UPDATE:
940-
InternalMessageHandler.HandleNetworkedVarUpdate(clientId, messageStream);
962+
InternalMessageHandler.HandleNetworkedVarUpdate(clientId, messageStream, bufferCallback);
941963
break;
942964
case MLAPIConstants.MLAPI_SERVER_RPC:
943-
if (IsServer) InternalMessageHandler.HandleServerRPC(clientId, messageStream);
965+
if (IsServer) InternalMessageHandler.HandleServerRPC(clientId, messageStream, bufferCallback);
944966
break;
945967
case MLAPIConstants.MLAPI_SERVER_RPC_REQUEST:
946-
if (IsServer) InternalMessageHandler.HandleServerRPCRequest(clientId, messageStream, channelName, security);
968+
if (IsServer) InternalMessageHandler.HandleServerRPCRequest(clientId, messageStream, channelName, security, bufferCallback);
947969
break;
948970
case MLAPIConstants.MLAPI_SERVER_RPC_RESPONSE:
949971
if (IsClient) InternalMessageHandler.HandleServerRPCResponse(clientId, messageStream);
950972
break;
951973
case MLAPIConstants.MLAPI_CLIENT_RPC:
952-
if (IsClient) InternalMessageHandler.HandleClientRPC(clientId, messageStream);
974+
if (IsClient) InternalMessageHandler.HandleClientRPC(clientId, messageStream, bufferCallback);
953975
break;
954976
case MLAPIConstants.MLAPI_CLIENT_RPC_REQUEST:
955-
if (IsClient) InternalMessageHandler.HandleClientRPCRequest(clientId, messageStream, channelName, security);
977+
if (IsClient) InternalMessageHandler.HandleClientRPCRequest(clientId, messageStream, channelName, security, bufferCallback);
956978
break;
957979
case MLAPIConstants.MLAPI_CLIENT_RPC_RESPONSE:
958980
if (IsServer) InternalMessageHandler.HandleClientRPCResponse(clientId, messageStream);

MLAPI/Messaging/InternalMessageHandler.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ internal static void HandleTimeSync(ulong clientId, Stream stream, float receive
458458
}
459459
}
460460

461-
internal static void HandleNetworkedVarDelta(ulong clientId, Stream stream)
461+
internal static void HandleNetworkedVarDelta(ulong clientId, Stream stream, Action<ulong> bufferCallback)
462462
{
463463
if (!NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar)
464464
{
@@ -481,6 +481,10 @@ internal static void HandleNetworkedVarDelta(ulong clientId, Stream stream)
481481
}
482482
NetworkedBehaviour.HandleNetworkedVarDeltas(instance.networkedVarFields, stream, clientId, instance);
483483
}
484+
else if (NetworkSceneManager.sceneBufferedNetworkIds.ContainsKey(networkId))
485+
{
486+
bufferCallback(networkId);
487+
}
484488
else
485489
{
486490
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("NetworkedVar message recieved for a non existant object with id: " + networkId);
@@ -489,7 +493,7 @@ internal static void HandleNetworkedVarDelta(ulong clientId, Stream stream)
489493
}
490494
}
491495

492-
internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream)
496+
internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream, Action<ulong> bufferCallback)
493497
{
494498
if (!NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar)
495499
{
@@ -512,6 +516,10 @@ internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream)
512516
}
513517
NetworkedBehaviour.HandleNetworkedVarUpdate(instance.networkedVarFields, stream, clientId, instance);
514518
}
519+
else if (NetworkSceneManager.sceneBufferedNetworkIds.ContainsKey(networkId))
520+
{
521+
bufferCallback(networkId);
522+
}
515523
else
516524
{
517525
if (LogHelper.CurrentLogLevel <= LogLevel.Normal) LogHelper.LogWarning("NetworkedVar message recieved for a non existant object with id: " + networkId);
@@ -520,7 +528,7 @@ internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream)
520528
}
521529
}
522530

523-
internal static void HandleServerRPC(ulong clientId, Stream stream)
531+
internal static void HandleServerRPC(ulong clientId, Stream stream, Action<ulong> bufferCallback)
524532
{
525533
using (PooledBitReader reader = PooledBitReader.Get(stream))
526534
{
@@ -536,10 +544,14 @@ internal static void HandleServerRPC(ulong clientId, Stream stream)
536544
behaviour.OnRemoteServerRPC(hash, clientId, stream);
537545
}
538546
}
547+
else if (NetworkSceneManager.sceneBufferedNetworkIds.ContainsKey(networkId))
548+
{
549+
bufferCallback(networkId);
550+
}
539551
}
540552
}
541553

542-
internal static void HandleServerRPCRequest(ulong clientId, Stream stream, string channelName, SecuritySendFlags security)
554+
internal static void HandleServerRPCRequest(ulong clientId, Stream stream, string channelName, SecuritySendFlags security, Action<ulong> bufferCallback)
543555
{
544556
using (PooledBitReader reader = PooledBitReader.Get(stream))
545557
{
@@ -567,6 +579,10 @@ internal static void HandleServerRPCRequest(ulong clientId, Stream stream, strin
567579
}
568580
}
569581
}
582+
else if (NetworkSceneManager.sceneBufferedNetworkIds.ContainsKey(networkId))
583+
{
584+
bufferCallback(networkId);
585+
}
570586
}
571587
}
572588

@@ -589,7 +605,7 @@ internal static void HandleServerRPCResponse(ulong clientId, Stream stream)
589605
}
590606
}
591607

592-
internal static void HandleClientRPC(ulong clientId, Stream stream)
608+
internal static void HandleClientRPC(ulong clientId, Stream stream, Action<ulong> bufferCallback)
593609
{
594610
using (PooledBitReader reader = PooledBitReader.Get(stream))
595611
{
@@ -605,10 +621,14 @@ internal static void HandleClientRPC(ulong clientId, Stream stream)
605621
behaviour.OnRemoteClientRPC(hash, clientId, stream);
606622
}
607623
}
624+
else if (NetworkSceneManager.sceneBufferedNetworkIds.ContainsKey(networkId))
625+
{
626+
bufferCallback(networkId);
627+
}
608628
}
609629
}
610630

611-
internal static void HandleClientRPCRequest(ulong clientId, Stream stream, string channelName, SecuritySendFlags security)
631+
internal static void HandleClientRPCRequest(ulong clientId, Stream stream, string channelName, SecuritySendFlags security, Action<ulong> bufferCallback)
612632
{
613633
using (PooledBitReader reader = PooledBitReader.Get(stream))
614634
{
@@ -636,6 +656,10 @@ internal static void HandleClientRPCRequest(ulong clientId, Stream stream, strin
636656
}
637657
}
638658
}
659+
else if (NetworkSceneManager.sceneBufferedNetworkIds.ContainsKey(networkId))
660+
{
661+
bufferCallback(networkId);
662+
}
639663
}
640664
}
641665

MLAPI/SceneManagement/NetworkSceneManager.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ public static class NetworkSceneManager
3939
internal static Guid currentSceneSwitchProgressGuid = new Guid();
4040
internal static bool isSpawnedObjectsPendingInDontDestroyOnLoad = false;
4141

42+
internal static Dictionary<ulong, Queue<BufferedMessage>> sceneBufferedNetworkIds = new Dictionary<ulong, Queue<BufferedMessage>>();
43+
44+
internal struct BufferedMessage
45+
{
46+
internal ulong sender;
47+
internal string channelName;
48+
internal ArraySegment<byte> payload;
49+
internal PooledBitStream pool;
50+
internal float receiveTime;
51+
}
52+
4253
internal static void SetCurrentSceneIndex()
4354
{
4455
if (!sceneNameToIndex.ContainsKey(SceneManager.GetActiveScene().name))
@@ -137,6 +148,23 @@ internal static void OnSceneSwitch(uint sceneIndex, Guid switchSceneGuid, Stream
137148

138149
string sceneName = sceneIndexToString[sceneIndex];
139150

151+
// Buffering pos
152+
long startPos = objectStream.Position;
153+
154+
// Buffering reader
155+
using (PooledBitReader reader = PooledBitReader.Get(objectStream))
156+
{
157+
uint newObjectsCount = reader.ReadUInt32Packed();
158+
159+
for (int i = 0; i < newObjectsCount; i++)
160+
{
161+
sceneBufferedNetworkIds.Add(reader.ReadUInt64Packed(), new Queue<BufferedMessage>());
162+
}
163+
}
164+
165+
// Restore pos
166+
objectStream.Position = startPos;
167+
140168
AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
141169
nextSceneName = sceneName;
142170

@@ -241,6 +269,15 @@ private static void OnSceneUnloadServer(Guid switchSceneGuid)
241269

242270
writer.WriteUInt32Packed(sceneObjectsToSpawn);
243271

272+
// Prefix with all the networkIds
273+
for (int i = 0; i < newSceneObjects.Count; i++)
274+
{
275+
if (newSceneObjects[i].observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId))
276+
{
277+
writer.WriteUInt64Packed(newSceneObjects[i].NetworkId);
278+
}
279+
}
280+
244281
for (int i = 0; i < newSceneObjects.Count; i++)
245282
{
246283
if (newSceneObjects[i].observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId))
@@ -320,6 +357,12 @@ private static void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStrea
320357
{
321358
uint newObjectsCount = reader.ReadUInt32Packed();
322359

360+
// Read the prefixes
361+
for (int i = 0; i < newObjectsCount; i++)
362+
{
363+
reader.ReadUInt64Packed();
364+
}
365+
323366
for (int i = 0; i < newObjectsCount; i++)
324367
{
325368
bool isPlayerObject = reader.ReadBool();
@@ -345,6 +388,22 @@ private static void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStrea
345388

346389
NetworkedObject networkedObject = SpawnManager.CreateLocalNetworkedObject(false, 0, prefabHash, parentNetworkId, position, rotation);
347390
SpawnManager.SpawnNetworkedObjectLocally(networkedObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, false);
391+
392+
// Apply buffered messages
393+
if (sceneBufferedNetworkIds.ContainsKey(networkId))
394+
{
395+
Queue<BufferedMessage> bufferedMessages = sceneBufferedNetworkIds[networkId];
396+
sceneBufferedNetworkIds.Remove(networkId);
397+
398+
while (bufferedMessages.Count > 0)
399+
{
400+
BufferedMessage message = bufferedMessages.Dequeue();
401+
402+
NetworkingManager.Singleton.HandleIncomingData(message.sender, message.channelName, message.payload, message.receiveTime);
403+
404+
message.pool.Dispose();
405+
}
406+
}
348407
}
349408
}
350409
}
@@ -358,6 +417,12 @@ private static void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStrea
358417
{
359418
uint newObjectsCount = reader.ReadUInt32Packed();
360419

420+
// Read the prefixes
421+
for (int i = 0; i < newObjectsCount; i++)
422+
{
423+
reader.ReadUInt64Packed();
424+
}
425+
361426
for (int i = 0; i < newObjectsCount; i++)
362427
{
363428
bool isPlayerObject = reader.ReadBool();
@@ -375,6 +440,22 @@ private static void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStrea
375440

376441
NetworkedObject networkedObject = SpawnManager.CreateLocalNetworkedObject(true, instanceId, 0, parentNetworkId, null, null);
377442
SpawnManager.SpawnNetworkedObjectLocally(networkedObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, false);
443+
444+
// Apply buffered messages
445+
if (sceneBufferedNetworkIds.ContainsKey(networkId))
446+
{
447+
Queue<BufferedMessage> bufferedMessages = sceneBufferedNetworkIds[networkId];
448+
sceneBufferedNetworkIds.Remove(networkId);
449+
450+
while (bufferedMessages.Count > 0)
451+
{
452+
BufferedMessage message = bufferedMessages.Dequeue();
453+
454+
NetworkingManager.Singleton.HandleIncomingData(message.sender, message.channelName, message.payload, message.receiveTime);
455+
456+
message.pool.Dispose();
457+
}
458+
}
378459
}
379460
}
380461
}

0 commit comments

Comments
 (0)