Skip to content

Commit 3e96cf9

Browse files
Jean-Sébastien Fauteux0xFA11
andauthored
feat: Add RPC Name Lookup Table Provided by NetworkBehaviourILPP (#875)
* Adding RPC Name Information through ILPP and Code Gen (MTT-802) * Updated based on comments and feedback * Updating comment to reflect better * Setup a list to avoid manipulating the string. Updated the naming around to better identify the two lists * Using compiled assembly defines list instead of macros * Passing defines as argument instead of storing them. Updated the comment in network manager to better reflect what is going on. * minor refactor Co-authored-by: M. Fatih MAR <mfatihmar@gmail.com>
1 parent 92cd9cc commit 3e96cf9

File tree

3 files changed

+61
-19
lines changed

3 files changed

+61
-19
lines changed

com.unity.multiplayer.mlapi/Editor/CodeGen/NetworkBehaviourILPP.cs

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
5757
mainModule.GetTypes()
5858
.Where(t => t.IsSubclassOf(CodeGenHelpers.NetworkBehaviour_FullName))
5959
.ToList()
60-
.ForEach(ProcessNetworkBehaviour);
60+
.ForEach(b => ProcessNetworkBehaviour(b, compiledAssembly.Defines));
6161
}
6262
else
6363
{
@@ -95,6 +95,8 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
9595
private FieldReference m_NetworkManager_LogLevel_FieldRef;
9696
private FieldReference m_NetworkManager_ntable_FieldRef;
9797
private MethodReference m_NetworkManager_ntable_Add_MethodRef;
98+
private FieldReference m_NetworkManager_rpc_name_table_FieldRef;
99+
private MethodReference m_NetworkManager_rpc_name_table_Add_MethodRef;
98100
private TypeReference m_NetworkBehaviour_TypeRef;
99101
private MethodReference m_NetworkBehaviour_BeginSendServerRpc_MethodRef;
100102
private MethodReference m_NetworkBehaviour_EndSendServerRpc_MethodRef;
@@ -164,6 +166,7 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
164166
private const string k_NetworkManager_LogLevel = nameof(NetworkManager.LogLevel);
165167
#pragma warning disable 618
166168
private const string k_NetworkManager_ntable = nameof(NetworkManager.__ntable);
169+
private const string k_NetworkManager_rpc_name_table = nameof(NetworkManager.__rpc_name_table);
167170

168171
private const string k_NetworkBehaviour_BeginSendServerRpc = nameof(NetworkBehaviour.__beginSendServerRpc);
169172
private const string k_NetworkBehaviour_EndSendServerRpc = nameof(NetworkBehaviour.__endSendServerRpc);
@@ -235,6 +238,10 @@ private bool ImportReferences(ModuleDefinition moduleDefinition)
235238
m_NetworkManager_ntable_FieldRef = moduleDefinition.ImportReference(fieldInfo);
236239
m_NetworkManager_ntable_Add_MethodRef = moduleDefinition.ImportReference(fieldInfo.FieldType.GetMethod("Add"));
237240
break;
241+
case k_NetworkManager_rpc_name_table:
242+
m_NetworkManager_rpc_name_table_FieldRef = moduleDefinition.ImportReference(fieldInfo);
243+
m_NetworkManager_rpc_name_table_Add_MethodRef = moduleDefinition.ImportReference(fieldInfo.FieldType.GetMethod("Add"));
244+
break;
238245
}
239246
}
240247

@@ -523,9 +530,13 @@ private bool ImportReferences(ModuleDefinition moduleDefinition)
523530
return true;
524531
}
525532

526-
private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
533+
private void ProcessNetworkBehaviour(TypeDefinition typeDefinition, string[] assemblyDefines)
527534
{
528-
var staticHandlers = new List<(uint Hash, MethodDefinition Method)>();
535+
var rpcHandlers = new List<(uint RpcHash, MethodDefinition RpcHandler)>();
536+
var rpcNames = new List<(uint RpcHash, string RpcName)>();
537+
538+
bool isEditorOrDevelopment = assemblyDefines.Contains("UNITY_EDITOR") || assemblyDefines.Contains("DEVELOPMENT_BUILD");
539+
529540
foreach (var methodDefinition in typeDefinition.Methods)
530541
{
531542
var rpcAttribute = CheckAndGetRPCAttribute(methodDefinition);
@@ -541,10 +552,16 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
541552
}
542553

543554
InjectWriteAndCallBlocks(methodDefinition, rpcAttribute, methodDefHash);
544-
staticHandlers.Add((methodDefHash, GenerateStaticHandler(methodDefinition, rpcAttribute)));
555+
556+
rpcHandlers.Add((methodDefHash, GenerateStaticHandler(methodDefinition, rpcAttribute)));
557+
558+
if (isEditorOrDevelopment)
559+
{
560+
rpcNames.Add((methodDefHash, methodDefinition.Name));
561+
}
545562
}
546563

547-
if (staticHandlers.Count > 0)
564+
if (rpcHandlers.Count > 0 || rpcNames.Count > 0)
548565
{
549566
var staticCtorMethodDef = typeDefinition.GetStaticConstructor();
550567
if (staticCtorMethodDef == null)
@@ -562,24 +579,29 @@ private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
562579

563580
var instructions = new List<Instruction>();
564581
var processor = staticCtorMethodDef.Body.GetILProcessor();
565-
foreach (var (hash, method) in staticHandlers)
566-
{
567-
if (hash == 0 || method == null)
568-
{
569-
continue;
570-
}
571582

572-
typeDefinition.Methods.Add(method);
583+
foreach (var (rpcHash, rpcHandler) in rpcHandlers)
584+
{
585+
typeDefinition.Methods.Add(rpcHandler);
573586

574-
// NetworkManager.__ntable.Add(HandlerHash, HandlerMethod);
587+
// NetworkManager.__ntable.Add(RpcHash, HandleFunc);
575588
instructions.Add(processor.Create(OpCodes.Ldsfld, m_NetworkManager_ntable_FieldRef));
576-
instructions.Add(processor.Create(OpCodes.Ldc_I4, unchecked((int)hash)));
589+
instructions.Add(processor.Create(OpCodes.Ldc_I4, unchecked((int)rpcHash)));
577590
instructions.Add(processor.Create(OpCodes.Ldnull));
578-
instructions.Add(processor.Create(OpCodes.Ldftn, method));
591+
instructions.Add(processor.Create(OpCodes.Ldftn, rpcHandler));
579592
instructions.Add(processor.Create(OpCodes.Newobj, m_NetworkHandlerDelegateCtor_MethodRef));
580593
instructions.Add(processor.Create(OpCodes.Call, m_NetworkManager_ntable_Add_MethodRef));
581594
}
582595

596+
foreach (var (rpcHash, rpcName) in rpcNames)
597+
{
598+
// NetworkManager.__rpc_name_table.Add(RpcHash, RpcName);
599+
instructions.Add(processor.Create(OpCodes.Ldsfld, m_NetworkManager_rpc_name_table_FieldRef));
600+
instructions.Add(processor.Create(OpCodes.Ldc_I4, unchecked((int)rpcHash)));
601+
instructions.Add(processor.Create(OpCodes.Ldstr, rpcName));
602+
instructions.Add(processor.Create(OpCodes.Call, m_NetworkManager_rpc_name_table_Add_MethodRef));
603+
}
604+
583605
instructions.Reverse();
584606
instructions.ForEach(instruction => processor.Body.Instructions.Insert(0, instruction));
585607
}

com.unity.multiplayer.mlapi/Editor/CodeGen/RuntimeAccessModifiersILPP.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#if UNITY_2020_2_OR_NEWER
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Linq;
45
using Mono.Cecil;
56
using Mono.Cecil.Cil;
67
using Unity.CompilationPipeline.Common.Diagnostics;
@@ -49,7 +50,7 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
4950
switch (typeDefinition.Name)
5051
{
5152
case nameof(NetworkManager):
52-
ProcessNetworkManager(typeDefinition);
53+
ProcessNetworkManager(typeDefinition, compiledAssembly.Defines);
5354
break;
5455
case nameof(NetworkBehaviour):
5556
ProcessNetworkBehaviour(typeDefinition);
@@ -81,14 +82,22 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
8182
return new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), m_Diagnostics);
8283
}
8384

84-
private void ProcessNetworkManager(TypeDefinition typeDefinition)
85+
private void ProcessNetworkManager(TypeDefinition typeDefinition, string[] assemblyDefines)
8586
{
8687
foreach (var fieldDefinition in typeDefinition.Fields)
8788
{
8889
if (fieldDefinition.Name == nameof(NetworkManager.__ntable))
8990
{
9091
fieldDefinition.IsPublic = true;
9192
}
93+
94+
if (assemblyDefines.Contains("UNITY_EDITOR") || assemblyDefines.Contains("DEVELOPMENT_BUILD"))
95+
{
96+
if (fieldDefinition.Name == nameof(NetworkManager.__rpc_name_table))
97+
{
98+
fieldDefinition.IsPublic = true;
99+
}
100+
}
92101
}
93102
}
94103

com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,21 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr
3535
#if UNITY_2020_2_OR_NEWER
3636
// RuntimeAccessModifiersILPP will make this `public`
3737
internal static readonly Dictionary<uint, Action<NetworkBehaviour, NetworkSerializer, __RpcParams>> __ntable = new Dictionary<uint, Action<NetworkBehaviour, NetworkSerializer, __RpcParams>>();
38-
#else
38+
39+
#if UNITY_EDITOR || DEVELOPMENT_BUILD
40+
// RuntimeAccessModifiersILPP will make this `public`
41+
internal static readonly Dictionary<uint, string> __rpc_name_table = new Dictionary<uint, string>();
42+
#else // !(UNITY_EDITOR || DEVELOPMENT_BUILD)
43+
// RuntimeAccessModifiersILPP and NetworkBehaviourILPP requires a variable with this name to exist when outside of Debug build or Editor.
44+
// If the name doesn't exist, generation and compilation errors occurs.
45+
// For the sake of consistency, we are using the same type.
46+
// Final note: this variable will not be used. Since it's never initialized, it will not be in the memory footprint.
47+
internal static readonly Dictionary<uint, string> __rpc_name_table = null;
48+
#endif // UNITY_EDITOR || DEVELOPMENT_BUILD
49+
#else // !UNITY_2020_2_OR_NEWER
3950
[Obsolete("Please do not use, will no longer be exposed in the future versions (framework internal)")]
4051
public static readonly Dictionary<uint, Action<NetworkBehaviour, NetworkSerializer, __RpcParams>> __ntable = new Dictionary<uint, Action<NetworkBehaviour, NetworkSerializer, __RpcParams>>();
41-
#endif
52+
#endif // UNITY_2020_2_OR_NEWER
4253
#pragma warning restore IDE1006 // restore naming rule violation check
4354

4455
#if DEVELOPMENT_BUILD || UNITY_EDITOR

0 commit comments

Comments
 (0)