@@ -609,6 +609,7 @@ private void CreateNetworkVariableTypeInitializers(AssemblyDefinition assembly,
609609 private const string k_NetworkVariableBase_Initialize = nameof ( NetworkVariableBase . Initialize ) ;
610610
611611 private const string k_RpcAttribute_Delivery = nameof ( RpcAttribute . Delivery ) ;
612+ private const string k_RpcAttribute_InvokePermission = nameof ( RpcAttribute . InvokePermission ) ;
612613 private const string k_ServerRpcAttribute_RequireOwnership = nameof ( ServerRpcAttribute . RequireOwnership ) ;
613614 private const string k_RpcParams_Server = nameof ( __RpcParams . Server ) ;
614615 private const string k_RpcParams_Client = nameof ( __RpcParams . Client ) ;
@@ -1311,7 +1312,7 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass
13111312 return ;
13121313 }
13131314 }
1314- var rpcHandlers = new List < ( uint RpcMethodId , MethodDefinition RpcHandler , string RpcMethodName ) > ( ) ;
1315+ var rpcHandlers = new List < ( uint RpcMethodId , MethodDefinition RpcHandler , string RpcMethodName , CustomAttribute rpcAttribute ) > ( ) ;
13151316
13161317 bool isEditorOrDevelopment = assemblyDefines . Contains ( "UNITY_EDITOR" ) || assemblyDefines . Contains ( "DEVELOPMENT_BUILD" ) ;
13171318
@@ -1342,7 +1343,7 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass
13421343
13431344 InjectWriteAndCallBlocks ( methodDefinition , rpcAttribute , rpcMethodId ) ;
13441345
1345- rpcHandlers . Add ( ( rpcMethodId , GenerateStaticHandler ( methodDefinition , rpcAttribute , rpcMethodId ) , methodDefinition . Name ) ) ;
1346+ rpcHandlers . Add ( ( rpcMethodId , GenerateStaticHandler ( methodDefinition , rpcAttribute , rpcMethodId ) , methodDefinition . Name , rpcAttribute ) ) ;
13461347 }
13471348
13481349 GenerateVariableInitialization ( typeDefinition ) ;
@@ -1424,7 +1425,7 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass
14241425 var instructions = new List < Instruction > ( ) ;
14251426 var processor = initializeRpcsMethodDef . Body . GetILProcessor ( ) ;
14261427
1427- foreach ( var ( rpcMethodId , rpcHandler , rpcMethodName ) in rpcHandlers )
1428+ foreach ( var ( rpcMethodId , rpcHandler , rpcMethodName , rpcAttribute ) in rpcHandlers )
14281429 {
14291430 typeDefinition . Methods . Add ( rpcHandler ) ;
14301431
@@ -1435,12 +1436,35 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass
14351436 callMethod = callMethod . MakeGeneric ( genericTypes . ToArray ( ) ) ;
14361437 }
14371438
1438- // __registerRpc(RpcMethodId, HandleFunc, methodName);
1439+ var isClientRpc = rpcAttribute . AttributeType . FullName == CodeGenHelpers . ClientRpcAttribute_FullName ;
1440+
1441+ var invokePermission = RpcInvokePermission . Anyone ;
1442+
1443+ foreach ( var attrField in rpcAttribute . Fields )
1444+ {
1445+ switch ( attrField . Name )
1446+ {
1447+ case k_ServerRpcAttribute_RequireOwnership :
1448+ invokePermission = ( attrField . Argument . Type == rpcHandler . Module . TypeSystem . Boolean && ( bool ) attrField . Argument . Value ) ? RpcInvokePermission . Owner : RpcInvokePermission . Anyone ;
1449+ break ;
1450+ case k_RpcAttribute_InvokePermission :
1451+ invokePermission = ( RpcInvokePermission ) attrField . Argument . Value ;
1452+ break ;
1453+ }
1454+ }
1455+
1456+ if ( isClientRpc )
1457+ {
1458+ invokePermission = RpcInvokePermission . Server ;
1459+ }
1460+
1461+ // __registerRpc(RpcMethodId, HandleFunc, invokePermission, methodName);
14391462 instructions . Add ( processor . Create ( OpCodes . Ldarg_0 ) ) ;
14401463 instructions . Add ( processor . Create ( OpCodes . Ldc_I4 , unchecked ( ( int ) rpcMethodId ) ) ) ;
14411464 instructions . Add ( processor . Create ( OpCodes . Ldnull ) ) ;
14421465 instructions . Add ( processor . Create ( OpCodes . Ldftn , callMethod ) ) ;
14431466 instructions . Add ( processor . Create ( OpCodes . Newobj , m_NetworkHandlerDelegateCtor_MethodRef ) ) ;
1467+ instructions . Add ( processor . Create ( OpCodes . Ldc_I4 , ( int ) invokePermission ) ) ;
14441468 instructions . Add ( processor . Create ( OpCodes . Ldstr , rpcMethodName ) ) ;
14451469 instructions . Add ( processor . Create ( OpCodes . Call , m_NetworkBehaviour___registerRpc_MethodRef ) ) ;
14461470 }
@@ -1517,6 +1541,7 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] ass
15171541 private CustomAttribute CheckAndGetRpcAttribute ( MethodDefinition methodDefinition )
15181542 {
15191543 CustomAttribute rpcAttribute = null ;
1544+
15201545 foreach ( var customAttribute in methodDefinition . CustomAttributes )
15211546 {
15221547 var customAttributeType_FullName = customAttribute . AttributeType . FullName ;
@@ -1600,6 +1625,30 @@ private CustomAttribute CheckAndGetRpcAttribute(MethodDefinition methodDefinitio
16001625
16011626 return null ;
16021627 }
1628+
1629+ bool hasRequireOwnership = false , hasInvokePermission = false ;
1630+
1631+ foreach ( var argument in rpcAttribute . Fields )
1632+ {
1633+ switch ( argument . Name )
1634+ {
1635+ case k_ServerRpcAttribute_RequireOwnership :
1636+ hasRequireOwnership = true ;
1637+ break ;
1638+ case k_RpcAttribute_InvokePermission :
1639+ hasInvokePermission = true ;
1640+ break ;
1641+ default :
1642+ break ;
1643+ }
1644+ }
1645+
1646+ if ( hasRequireOwnership && hasInvokePermission )
1647+ {
1648+ m_Diagnostics . AddError ( "Rpc attribute cannot declare both RequireOwnership and InvokePermission!" ) ;
1649+ return null ;
1650+ }
1651+
16031652 // Checks for IsSerializable are moved to later as the check is now done by dynamically seeing if any valid
16041653 // serializer OR extension method exists for it.
16051654 return rpcAttribute ;
@@ -2346,6 +2395,7 @@ private void InjectWriteAndCallBlocks(MethodDefinition methodDefinition, CustomA
23462395 m_Diagnostics. AddError ( $ "{ nameof ( RpcAttribute ) } contains field { field } which is not present in { nameof ( RpcAttribute . RpcAttributeParams ) } .") ;
23472396 }
23482397 }
2398+
23492399 instructions. Add ( processor . Create ( OpCodes . Ldloc , rpcAttributeParamsIdx ) ) ;
23502400
23512401 // defaultTarget
@@ -2845,19 +2895,28 @@ private MethodDefinition GenerateStaticHandler(MethodDefinition methodDefinition
28452895 var processor = rpcHandler. Body. GetILProcessor( ) ;
28462896
28472897 var isServerRpc = rpcAttribute. AttributeType. FullName == CodeGenHelpers. ServerRpcAttribute_FullName;
2848- var isCientRpc = rpcAttribute. AttributeType. FullName == CodeGenHelpers. ClientRpcAttribute_FullName;
2898+ var isClientRpc = rpcAttribute. AttributeType. FullName == CodeGenHelpers. ClientRpcAttribute_FullName;
28492899 var isGenericRpc = rpcAttribute. AttributeType. FullName == CodeGenHelpers. RpcAttribute_FullName;
2850- var requireOwnership = true ; // default value MUST be == `ServerRpcAttribute.RequireOwnership`
2900+ var invokePermission = RpcInvokePermission . Anyone ;
28512901 foreach ( var attrField in rpcAttribute. Fields)
28522902 {
28532903 switch ( attrField. Name)
28542904 {
28552905 case k_ServerRpcAttribute_RequireOwnership:
2856- requireOwnership = attrField. Argument. Type == typeSystem. Boolean && ( bool ) attrField. Argument. Value;
2906+ invokePermission = ( attrField. Argument. Type == typeSystem. Boolean && ( bool ) attrField. Argument. Value) ? RpcInvokePermission. Owner : RpcInvokePermission. Anyone;
2907+ break ;
2908+ case k_RpcAttribute_InvokePermission:
2909+ invokePermission = ( RpcInvokePermission) attrField. Argument. Value;
28572910 break ;
28582911 }
28592912 }
28602913
2914+ // legacy ClientRpc should always be RpcInvokePermission.Server
2915+ if ( isClientRpc)
2916+ {
2917+ invokePermission = RpcInvokePermission. Server;
2918+ }
2919+
28612920 rpcHandler. Body. InitLocals = true;
28622921 // NetworkManager networkManager;
28632922 rpcHandler. Body. Variables. Add( new VariableDefinition( m_NetworkManager_TypeRef) ) ;
@@ -2883,7 +2942,7 @@ private MethodDefinition GenerateStaticHandler(MethodDefinition methodDefinition
28832942 processor. Append( lastInstr) ;
28842943 }
28852944
2886- if ( isServerRpc && requireOwnership )
2945+ if ( isServerRpc && invokePermission == RpcInvokePermission . Owner )
28872946 {
28882947 var roReturnInstr = processor. Create( OpCodes. Ret) ;
28892948 var roLastInstr = processor. Create( OpCodes. Nop) ;
@@ -2917,6 +2976,42 @@ private MethodDefinition GenerateStaticHandler(MethodDefinition methodDefinition
29172976
29182977 processor. Append( logNextInstr) ;
29192978
2979+ processor. Append( roReturnInstr) ;
2980+ processor. Append( roLastInstr) ;
2981+ } else if ( invokePermission == RpcInvokePermission. Server)
2982+ {
2983+ var roReturnInstr = processor. Create( OpCodes. Ret) ;
2984+ var roLastInstr = processor. Create( OpCodes. Nop) ;
2985+
2986+ // if (rpcParams.Server.Receive.SenderClientId != NetworkManager.IsServer) { ... } return;
2987+ processor. Emit( OpCodes. Ldarg_2) ;
2988+ processor. Emit( OpCodes. Ldfld, m_RpcParams_Server_FieldRef) ;
2989+ processor. Emit( OpCodes. Ldfld, m_ServerRpcParams_Receive_FieldRef) ;
2990+ processor. Emit( OpCodes. Ldfld, m_ServerRpcParams_Receive_SenderClientId_FieldRef) ;
2991+ processor. Emit( OpCodes. Ldarg_0) ;
2992+ processor. Emit( OpCodes. Call, m_NetworkManager_getIsServer_MethodRef) ;
2993+ processor. Emit( OpCodes. Ceq) ;
2994+ processor. Emit( OpCodes. Ldc_I4, 0 ) ;
2995+ processor. Emit( OpCodes. Ceq) ;
2996+ processor. Emit( OpCodes. Brfalse, roLastInstr) ;
2997+
2998+ var logNextInstr = processor. Create( OpCodes. Nop) ;
2999+
3000+ // if (LogLevel.Normal > networkManager.LogLevel)
3001+ processor. Emit( OpCodes. Ldloc, netManLocIdx) ;
3002+ processor. Emit( OpCodes. Ldfld, m_NetworkManager_LogLevel_FieldRef) ;
3003+ processor. Emit( OpCodes. Ldc_I4, ( int ) LogLevel. Normal) ;
3004+ processor. Emit( OpCodes. Cgt) ;
3005+ processor. Emit( OpCodes. Ldc_I4, 0 ) ;
3006+ processor. Emit( OpCodes. Ceq) ;
3007+ processor. Emit( OpCodes. Brfalse, logNextInstr) ;
3008+
3009+ // Debug.LogError(...);
3010+ processor. Emit( OpCodes. Ldstr, "Only the server can invoke an Rpc with RpcInvokePermission. Server! ") ;
3011+ processor. Emit( OpCodes. Call, m_Debug_LogError_MethodRef) ;
3012+
3013+ processor. Append( logNextInstr) ;
3014+
29203015 processor. Append( roReturnInstr) ;
29213016 processor. Append( roLastInstr) ;
29223017 }
0 commit comments