@@ -30,15 +30,16 @@ public abstract class NetworkedBehaviour : MonoBehaviour
3030 /// <summary>
3131 /// Gets if we are executing as server
3232 /// </summary>
33- protected bool isServer => NetworkingManager . singleton . isServer ;
33+ protected bool isServer => isRunning && NetworkingManager . singleton . isServer ;
3434 /// <summary>
3535 /// Gets if we are executing as client
3636 /// </summary>
37- protected bool isClient => NetworkingManager . singleton . isClient ;
37+ protected bool isClient => isRunning && NetworkingManager . singleton . isClient ;
3838 /// <summary>
3939 /// Gets if we are executing as Host, I.E Server and Client
4040 /// </summary>
41- protected bool isHost => NetworkingManager . singleton . isHost ;
41+ protected bool isHost => isRunning && NetworkingManager . singleton . isHost ;
42+ private bool isRunning => NetworkingManager . singleton == null || NetworkingManager . singleton . isListening ;
4243 /// <summary>
4344 /// Gets wheter or not the object has a owner
4445 /// </summary>
@@ -75,10 +76,23 @@ private void OnEnable()
7576 if ( _networkedObject == null )
7677 _networkedObject = GetComponentInParent < NetworkedObject > ( ) ;
7778
78- CacheAttributes ( ) ;
7979 NetworkedObject . NetworkedBehaviours . Add ( this ) ;
8080 OnEnabled ( ) ;
8181 }
82+
83+ private void OnDisable ( )
84+ {
85+ OnDisabled ( ) ;
86+ }
87+
88+ private void OnDestroy ( )
89+ {
90+ NetworkedObject . NetworkedBehaviours . Remove ( this ) ; // O(n)
91+ CachedClientRpcs . Remove ( this ) ;
92+ CachedServerRpcs . Remove ( this ) ;
93+ OnDestroyed ( ) ;
94+ }
95+
8296 internal bool networkedStartInvoked = false ;
8397 /// <summary>
8498 /// Gets called when message handlers are ready to be registered and the networking is setup
@@ -189,17 +203,6 @@ protected NetworkedBehaviour GetBehaviour(ushort id)
189203 return networkedObject . GetBehaviourAtOrderIndex ( id ) ;
190204 }
191205
192- private void OnDisable ( )
193- {
194- OnDisabled ( ) ;
195- }
196-
197- private void OnDestroy ( )
198- {
199- NetworkedObject . NetworkedBehaviours . Remove ( this ) ; // O(n)
200- OnDestroyed ( ) ;
201- }
202-
203206 #region NetworkedVar
204207
205208 private bool networkedVarInit = false ;
@@ -296,7 +299,7 @@ internal void NetworkedVarUpdate()
296299 if ( isServer )
297300 InternalMessageHandler . Send ( clientId , MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA , channelsForVarGroups [ j ] , stream ) ;
298301 else
299- InternalMessageHandler . Send ( NetworkingManager . singleton . NetworkConfig . NetworkTransport . ServerClientId , MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA , channelsForVarGroups [ j ] , stream ) ;
302+ InternalMessageHandler . Send ( NetworkingManager . singleton . ServerClientId , MLAPIConstants . MLAPI_NETWORKED_VAR_DELTA , channelsForVarGroups [ j ] , stream ) ;
300303 }
301304 }
302305 }
@@ -360,10 +363,10 @@ internal void HandleNetworkedVarUpdate(Stream stream, uint clientId)
360363 #endregion
361364
362365 #region MESSAGING_SYSTEM
363- private static readonly Dictionary < Type , Dictionary < ulong , ClientRPC > > CachedClientRpcs = new Dictionary < Type , Dictionary < ulong , ClientRPC > > ( ) ;
364- private static readonly Dictionary < Type , Dictionary < ulong , ServerRPC > > CachedServerRpcs = new Dictionary < Type , Dictionary < ulong , ServerRPC > > ( ) ;
366+ private readonly Dictionary < NetworkedBehaviour , Dictionary < ulong , ClientRPC > > CachedClientRpcs = new Dictionary < NetworkedBehaviour , Dictionary < ulong , ClientRPC > > ( ) ;
367+ private readonly Dictionary < NetworkedBehaviour , Dictionary < ulong , ServerRPC > > CachedServerRpcs = new Dictionary < NetworkedBehaviour , Dictionary < ulong , ServerRPC > > ( ) ;
368+ private static readonly Dictionary < Type , MethodInfo [ ] > Methods = new Dictionary < Type , MethodInfo [ ] > ( ) ;
365369 private static readonly Dictionary < ulong , string > HashResults = new Dictionary < ulong , string > ( ) ;
366- private static readonly HashSet < Type > CachedTypes = new HashSet < Type > ( ) ;
367370
368371 private ulong HashMethodName ( string name )
369372 {
@@ -382,13 +385,18 @@ private ulong HashMethodName(string name)
382385 private void CacheAttributes ( )
383386 {
384387 Type type = GetType ( ) ;
385- if ( CachedTypes . Contains ( type ) ) return ; //Already cached
386388
387- CachedTypes . Add ( type ) ;
388- CachedClientRpcs . Add ( type , new Dictionary < ulong , ClientRPC > ( ) ) ;
389- CachedServerRpcs . Add ( type , new Dictionary < ulong , ServerRPC > ( ) ) ;
390-
391- MethodInfo [ ] methods = type . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) ;
389+ CachedClientRpcs . Add ( this , new Dictionary < ulong , ClientRPC > ( ) ) ;
390+ CachedServerRpcs . Add ( this , new Dictionary < ulong , ServerRPC > ( ) ) ;
391+
392+ MethodInfo [ ] methods ;
393+ if ( Methods . ContainsKey ( type ) ) methods = Methods [ type ] ;
394+ else
395+ {
396+ methods = type . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) ;
397+ Methods . Add ( type , methods ) ;
398+ }
399+
392400 for ( int i = 0 ; i < methods . Length ; i ++ )
393401 {
394402 if ( methods [ i ] . IsDefined ( typeof ( ServerRPC ) , true ) )
@@ -403,7 +411,7 @@ private void CacheAttributes()
403411 if ( parameters . Length == 2 && parameters [ 0 ] . ParameterType == typeof ( uint ) && parameters [ 1 ] . ParameterType == typeof ( Stream ) )
404412 {
405413 //use delegate
406- attributes [ 0 ] . rpcDelegate = ( RpcDelegate ) Delegate . CreateDelegate ( typeof ( RpcDelegate ) , this , methods [ i ] , true ) ;
414+ attributes [ 0 ] . rpcDelegate = ( RpcDelegate ) Delegate . CreateDelegate ( typeof ( RpcDelegate ) , this , methods [ i ] . Name ) ;
407415 }
408416 else
409417 {
@@ -415,12 +423,12 @@ private void CacheAttributes()
415423 {
416424 if ( LogHelper . CurrentLogLevel <= LogLevel . Error ) LogHelper . LogError ( "Hash collision detected for RPC method. The method \" " + methods [ i ] . Name + "\" collides with the method \" " + HashResults [ hash ] + "\" . This can be solved by increasing the amount of bytes to use for hashing in the NetworkConfig or changing the name of one of the conflicting methods." ) ;
417425 }
418- else
426+ else if ( ! HashResults . ContainsKey ( hash ) )
419427 {
420428 HashResults . Add ( hash , methods [ i ] . Name ) ;
421429 }
422430
423- CachedServerRpcs [ type ] . Add ( hash , attributes [ 0 ] ) ;
431+ CachedServerRpcs [ this ] . Add ( hash , attributes [ 0 ] ) ;
424432 }
425433
426434 if ( methods [ i ] . IsDefined ( typeof ( ClientRPC ) , true ) )
@@ -435,21 +443,31 @@ private void CacheAttributes()
435443 if ( parameters . Length == 2 && parameters [ 0 ] . ParameterType == typeof ( uint ) && parameters [ 1 ] . ParameterType == typeof ( Stream ) )
436444 {
437445 //use delegate
438- attributes [ 0 ] . rpcDelegate = ( RpcDelegate ) Delegate . CreateDelegate ( typeof ( RpcDelegate ) , this , methods [ i ] , true ) ;
446+ attributes [ 0 ] . rpcDelegate = ( RpcDelegate ) Delegate . CreateDelegate ( typeof ( RpcDelegate ) , this , methods [ i ] . Name ) ;
439447 }
440448 else
441449 {
442450 attributes [ 0 ] . reflectionMethod = new ReflectionMehtod ( methods [ i ] ) ;
443451 }
444-
445- CachedClientRpcs [ type ] . Add ( HashMethodName ( methods [ i ] . Name ) , attributes [ 0 ] ) ;
452+
453+ ulong hash = HashMethodName ( methods [ i ] . Name ) ;
454+ if ( HashResults . ContainsKey ( hash ) && HashResults [ hash ] != methods [ i ] . Name )
455+ {
456+ if ( LogHelper . CurrentLogLevel <= LogLevel . Error ) LogHelper . LogError ( "Hash collision detected for RPC method. The method \" " + methods [ i ] . Name + "\" collides with the method \" " + HashResults [ hash ] + "\" . This can be solved by increasing the amount of bytes to use for hashing in the NetworkConfig or changing the name of one of the conflicting methods." ) ;
457+ }
458+ else if ( ! HashResults . ContainsKey ( hash ) )
459+ {
460+ HashResults . Add ( hash , methods [ i ] . Name ) ;
461+ }
462+
463+ CachedClientRpcs [ this ] . Add ( HashMethodName ( methods [ i ] . Name ) , attributes [ 0 ] ) ;
446464 }
447465 }
448466 }
449467
450468 internal void OnRemoteServerRPC ( ulong hash , uint senderClientId , Stream stream )
451469 {
452- if ( ! CachedServerRpcs . ContainsKey ( GetType ( ) ) || ! CachedServerRpcs [ GetType ( ) ] . ContainsKey ( hash ) )
470+ if ( ! CachedServerRpcs . ContainsKey ( this ) || ! CachedServerRpcs [ this ] . ContainsKey ( hash ) )
453471 {
454472 if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "ServerRPC request method not found" ) ;
455473 return ;
@@ -459,7 +477,7 @@ internal void OnRemoteServerRPC(ulong hash, uint senderClientId, Stream stream)
459477
460478 internal void OnRemoteClientRPC ( ulong hash , uint senderClientId , Stream stream )
461479 {
462- if ( ! CachedClientRpcs . ContainsKey ( GetType ( ) ) || ! CachedClientRpcs [ GetType ( ) ] . ContainsKey ( hash ) )
480+ if ( ! CachedClientRpcs . ContainsKey ( this ) || ! CachedClientRpcs [ this ] . ContainsKey ( hash ) )
463481 {
464482 if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "ClientRPC request method not found" ) ;
465483 return ;
@@ -469,43 +487,57 @@ internal void OnRemoteClientRPC(ulong hash, uint senderClientId, Stream stream)
469487
470488 private void InvokeServerRPCLocal ( ulong hash , uint senderClientId , Stream stream )
471489 {
472- if ( ! CachedServerRpcs . ContainsKey ( GetType ( ) ) || ! CachedServerRpcs [ GetType ( ) ] . ContainsKey ( hash ) )
490+ if ( ! CachedServerRpcs . ContainsKey ( this ) || ! CachedServerRpcs [ this ] . ContainsKey ( hash ) )
473491 return ;
474492
475- ServerRPC rpc = CachedServerRpcs [ GetType ( ) ] [ hash ] ;
493+ ServerRPC rpc = CachedServerRpcs [ this ] [ hash ] ;
476494
477495 if ( rpc . RequireOwnership && senderClientId != OwnerClientId )
478496 {
479497 if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "Only owner can invoke ServerRPC that is marked to require ownership" ) ;
480498 return ;
481499 }
482-
483- if ( rpc . reflectionMethod != null )
484- {
485- rpc . reflectionMethod . Invoke ( this , stream ) ;
486- }
487500
488- if ( rpc . rpcDelegate != null )
501+ //Create a new stream so that the stream they get ONLY contains user data and not MLAPI headers
502+ using ( PooledBitStream userStream = PooledBitStream . Get ( ) )
489503 {
490- rpc . rpcDelegate ( senderClientId , stream ) ;
504+ userStream . CopyUnreadFrom ( stream ) ;
505+ userStream . Position = 0 ;
506+
507+ if ( rpc . reflectionMethod != null )
508+ {
509+ rpc . reflectionMethod . Invoke ( this , userStream ) ;
510+ }
511+
512+ if ( rpc . rpcDelegate != null )
513+ {
514+ rpc . rpcDelegate ( senderClientId , userStream ) ;
515+ }
491516 }
492517 }
493518
494519 private void InvokeClientRPCLocal ( ulong hash , uint senderClientId , Stream stream )
495520 {
496- if ( ! CachedClientRpcs . ContainsKey ( GetType ( ) ) || ! CachedClientRpcs [ GetType ( ) ] . ContainsKey ( hash ) )
521+ if ( ! CachedClientRpcs . ContainsKey ( this ) || ! CachedClientRpcs [ this ] . ContainsKey ( hash ) )
497522 return ;
498523
499- ClientRPC rpc = CachedClientRpcs [ GetType ( ) ] [ hash ] ;
500-
501- if ( rpc . reflectionMethod != null )
502- {
503- rpc . reflectionMethod . Invoke ( this , stream ) ;
504- }
524+ ClientRPC rpc = CachedClientRpcs [ this ] [ hash ] ;
505525
506- if ( rpc . rpcDelegate != null )
526+ //Create a new stream so that the stream they get ONLY contains user data and not MLAPI headers
527+ using ( PooledBitStream userStream = PooledBitStream . Get ( ) )
507528 {
508- rpc . rpcDelegate ( senderClientId , stream ) ;
529+ userStream . CopyUnreadFrom ( stream ) ;
530+ userStream . Position = 0 ;
531+
532+ if ( rpc . reflectionMethod != null )
533+ {
534+ rpc . reflectionMethod . Invoke ( this , userStream ) ;
535+ }
536+
537+ if ( rpc . rpcDelegate != null )
538+ {
539+ rpc . rpcDelegate ( senderClientId , userStream ) ;
540+ }
509541 }
510542 }
511543
@@ -552,7 +584,7 @@ internal void SendClientRPCBoxed(ulong hash, uint clientId, params object[] para
552584
553585 internal void SendServerRPCPerformance ( ulong hash , Stream messageStream )
554586 {
555- if ( ! isClient )
587+ if ( ! isClient && isRunning )
556588 {
557589 //We are ONLY a server.
558590 if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "Only server and host can invoke ServerRPC" ) ;
@@ -573,14 +605,16 @@ internal void SendServerRPCPerformance(ulong hash, Stream messageStream)
573605 messageStream . Position = 0 ;
574606 InvokeServerRPCLocal ( hash , NetworkingManager . singleton . LocalClientId , messageStream ) ;
575607 }
576-
577- InternalMessageHandler . Send ( NetworkingManager . singleton . ServerClientId , MLAPIConstants . MLAPI_SERVER_RPC , "MLAPI_DEFAULT_MESSAGE" , stream ) ;
608+ else
609+ {
610+ InternalMessageHandler . Send ( NetworkingManager . singleton . ServerClientId , MLAPIConstants . MLAPI_SERVER_RPC , "MLAPI_DEFAULT_MESSAGE" , stream ) ;
611+ }
578612 }
579613 }
580614
581615 internal void SendClientRPCPerformance ( ulong hash , List < uint > clientIds , Stream messageStream )
582616 {
583- if ( ! isServer )
617+ if ( ! isServer && isRunning )
584618 {
585619 //We are NOT a server.
586620 if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "Only clients and host can invoke ClientRPC" ) ;
@@ -631,7 +665,7 @@ internal void SendClientRPCPerformance(ulong hash, List<uint> clientIds, Stream
631665
632666 internal void SendClientRPCPerformance ( ulong hash , uint clientId , Stream messageStream )
633667 {
634- if ( ! isServer )
668+ if ( ! isServer && isRunning )
635669 {
636670 //We are NOT a server.
637671 if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "Only clients and host can invoke ClientRPC" ) ;
0 commit comments