11using System ;
22using System . IO ;
33using System . Reflection ;
4+ using MLAPI . Logging ;
5+ using MLAPI . Serialization ;
46using MLAPI . Serialization . Pooled ;
57
68namespace MLAPI . Messaging
79{
810 internal class ReflectionMethod
911 {
10- private MethodInfo method ;
11- private Type [ ] parameterTypes ;
12- private object [ ] parameterRefs ;
13-
14- public ReflectionMethod ( MethodInfo methodInfo )
12+ internal readonly MethodInfo method ;
13+ internal readonly bool useDelegate ;
14+ internal readonly bool serverTarget ;
15+ private readonly bool requireOwnership ;
16+ private readonly int index ;
17+ private readonly Type [ ] parameterTypes ;
18+ private readonly object [ ] parameterRefs ;
19+
20+ internal static ReflectionMethod Create ( MethodInfo method , ParameterInfo [ ] parameters , int index )
21+ {
22+ RPCAttribute [ ] attributes = ( RPCAttribute [ ] ) method . GetCustomAttributes ( typeof ( RPCAttribute ) , true ) ;
23+
24+ if ( attributes . Length == 0 )
25+ return null ;
26+
27+ if ( attributes . Length > 1 )
28+ {
29+ if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "Having more than one ServerRPC or ClientRPC attribute per method is not supported." ) ;
30+ }
31+
32+ if ( method . ReturnType != typeof ( void ) && ! SerializationManager . IsTypeSupported ( method . ReturnType ) )
33+ {
34+ if ( LogHelper . CurrentLogLevel <= LogLevel . Error ) LogHelper . LogWarning ( "Invalid return type of RPC. Has to be either void or RpcResponse<T> with a serializable type" ) ;
35+ }
36+
37+ return new ReflectionMethod ( method , parameters , attributes [ 0 ] , index ) ;
38+ }
39+
40+ internal ReflectionMethod ( MethodInfo method , ParameterInfo [ ] parameters , RPCAttribute attribute , int index )
1541 {
16- method = methodInfo ;
17- ParameterInfo [ ] parameters = methodInfo . GetParameters ( ) ;
42+ this . method = method ;
43+ this . index = index ;
44+
45+ if ( attribute is ServerRPCAttribute serverRpcAttribute )
46+ {
47+ requireOwnership = serverRpcAttribute . RequireOwnership ;
48+ serverTarget = true ;
49+ }
50+ else
51+ {
52+ requireOwnership = false ;
53+ serverTarget = false ;
54+ }
55+
1856 parameterTypes = new Type [ parameters . Length ] ;
19- parameterRefs = new object [ parameters . Length ] ;
20-
21- for ( int i = 0 ; i < parameters . Length ; i ++ )
57+
58+ if ( parameters . Length == 2 && method . ReturnType == typeof ( void ) && parameters [ 0 ] . ParameterType == typeof ( ulong ) && parameters [ 1 ] . ParameterType == typeof ( Stream ) )
2259 {
23- parameterTypes [ i ] = parameters [ i ] . ParameterType ;
60+ useDelegate = true ;
61+ }
62+ else
63+ {
64+ useDelegate = false ;
65+
66+ parameterRefs = new object [ parameters . Length ] ;
67+
68+ for ( int i = 0 ; i < parameters . Length ; i ++ )
69+ {
70+ parameterTypes [ i ] = parameters [ i ] . ParameterType ;
71+ }
2472 }
2573 }
2674
27- internal object Invoke ( object instance , Stream stream )
75+ internal object Invoke ( NetworkedBehaviour target , ulong senderClientId , Stream stream )
76+ {
77+ if ( requireOwnership == true && senderClientId != target . OwnerClientId )
78+ {
79+ if ( LogHelper . CurrentLogLevel <= LogLevel . Normal ) LogHelper . LogWarning ( "Only owner can invoke ServerRPC that is marked to require ownership" ) ;
80+
81+ return null ;
82+ }
83+
84+ target . executingRpcSender = senderClientId ;
85+
86+ if ( stream . Position == 0 )
87+ {
88+ if ( useDelegate )
89+ {
90+ return InvokeDelegate ( target , senderClientId , stream ) ;
91+ }
92+ else
93+ {
94+ return InvokeReflected ( target , stream ) ;
95+ }
96+ }
97+ else
98+ {
99+ // Create a new stream so that the stream they get ONLY contains user data and not MLAPI headers
100+ using ( PooledBitStream userStream = PooledBitStream . Get ( ) )
101+ {
102+ userStream . CopyUnreadFrom ( stream ) ;
103+ userStream . Position = 0 ;
104+
105+ if ( useDelegate )
106+ {
107+ return InvokeDelegate ( target , senderClientId , stream ) ;
108+ }
109+ else
110+ {
111+ return InvokeReflected ( target , stream ) ;
112+ }
113+ }
114+ }
115+ }
116+
117+ private object InvokeReflected ( NetworkedBehaviour instance , Stream stream )
28118 {
29119 using ( PooledBitReader reader = PooledBitReader . Get ( stream ) )
30120 {
@@ -36,5 +126,12 @@ internal object Invoke(object instance, Stream stream)
36126 return method . Invoke ( instance , parameterRefs ) ;
37127 }
38128 }
129+
130+ private object InvokeDelegate ( NetworkedBehaviour target , ulong senderClientId , Stream stream )
131+ {
132+ target . rpcDelegates [ index ] ( senderClientId , stream ) ;
133+
134+ return null ;
135+ }
39136 }
40- }
137+ }
0 commit comments