1
1
using System ;
2
2
using System . IO ;
3
3
using System . Reflection ;
4
+ using MLAPI . Logging ;
5
+ using MLAPI . Serialization ;
4
6
using MLAPI . Serialization . Pooled ;
5
7
6
8
namespace MLAPI . Messaging
7
9
{
8
10
internal class ReflectionMethod
9
11
{
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 )
15
41
{
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
+
18
56
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 ) )
22
59
{
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
+ }
24
72
}
25
73
}
26
74
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 )
28
118
{
29
119
using ( PooledBitReader reader = PooledBitReader . Get ( stream ) )
30
120
{
@@ -36,5 +126,12 @@ internal object Invoke(object instance, Stream stream)
36
126
return method . Invoke ( instance , parameterRefs ) ;
37
127
}
38
128
}
129
+
130
+ private object InvokeDelegate ( NetworkedBehaviour target , ulong senderClientId , Stream stream )
131
+ {
132
+ target . rpcDelegates [ index ] ( senderClientId , stream ) ;
133
+
134
+ return null ;
135
+ }
39
136
}
40
- }
137
+ }
0 commit comments