Skip to content

Commit a87bfb0

Browse files
authored
refactor: ILPP to import references from companion modules (#2199)
1 parent 4bce448 commit a87bfb0

File tree

5 files changed

+318
-104
lines changed

5 files changed

+318
-104
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ Additional documentation and release notes are available at [Multiplayer Documen
1111

1212
### Fixed
1313

14-
- Fixed issue where `NetworkTransform` was not ending extrapolation for the previous state causing non-authoritative instances to become out of synch. (#2170)
14+
- Fixed ILPP `TypeLoadException` on WebGL on MacOS Editor and potentially other platforms. (#2199)
15+
- Fixed issue where `NetworkTransform` was not ending extrapolation for the previous state causing non-authoritative instances to become out of sync. (#2170)
1516
- Fixed issue where `NetworkTransform` was not continuing to interpolate for the remainder of the associated tick period. (#2170)
1617
- Fixed issue during `NetworkTransform.OnNetworkSpawn` for non-authoritative instances where it was initializing interpolators with the replicated network state which now only contains the transform deltas that occurred during a network tick and not the entire transform state. (#2170)
1718
- Fixed issue where `NetworkTransform` was not honoring the InLocalSpace property on the authority side during OnNetworkSpawn. (#2170)

com.unity.netcode.gameobjects/Editor/CodeGen/CodeGenHelpers.cs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ namespace Unity.Netcode.Editor.CodeGen
1515
{
1616
internal static class CodeGenHelpers
1717
{
18+
public const string DotnetModuleName = "netstandard.dll";
19+
public const string UnityModuleName = "UnityEngine.CoreModule.dll";
20+
public const string NetcodeModuleName = "Unity.Netcode.Runtime.dll";
21+
1822
public const string RuntimeAssemblyName = "Unity.Netcode.Runtime";
1923

2024
public static readonly string NetworkBehaviour_FullName = typeof(NetworkBehaviour).FullName;
@@ -380,5 +384,68 @@ public static AssemblyDefinition AssemblyDefinitionFor(ICompiledAssembly compile
380384

381385
return assemblyDefinition;
382386
}
387+
388+
public static (ModuleDefinition DotnetModule, ModuleDefinition UnityModule, ModuleDefinition NetcodeModule) FindBaseModules(AssemblyDefinition assemblyDefinition, PostProcessorAssemblyResolver assemblyResolver)
389+
{
390+
ModuleDefinition dotnetModule = null;
391+
ModuleDefinition unityModule = null;
392+
ModuleDefinition netcodeModule = null;
393+
394+
foreach (var module in assemblyDefinition.Modules)
395+
{
396+
if (dotnetModule == null && module.Name == DotnetModuleName)
397+
{
398+
dotnetModule = module;
399+
continue;
400+
}
401+
402+
if (unityModule == null && module.Name == UnityModuleName)
403+
{
404+
unityModule = module;
405+
continue;
406+
}
407+
408+
if (netcodeModule == null && module.Name == NetcodeModuleName)
409+
{
410+
netcodeModule = module;
411+
continue;
412+
}
413+
}
414+
415+
if (dotnetModule != null && unityModule != null && netcodeModule != null)
416+
{
417+
return (dotnetModule, unityModule, netcodeModule);
418+
}
419+
420+
foreach (var assemblyNameReference in assemblyDefinition.MainModule.AssemblyReferences)
421+
{
422+
foreach (var module in assemblyResolver.Resolve(assemblyNameReference).Modules)
423+
{
424+
if (dotnetModule == null && module.Name == DotnetModuleName)
425+
{
426+
dotnetModule = module;
427+
continue;
428+
}
429+
if (unityModule == null && module.Name == UnityModuleName)
430+
{
431+
unityModule = module;
432+
continue;
433+
}
434+
435+
if (netcodeModule == null && module.Name == NetcodeModuleName)
436+
{
437+
netcodeModule = module;
438+
continue;
439+
}
440+
}
441+
442+
if (dotnetModule != null && unityModule != null && netcodeModule != null)
443+
{
444+
return (dotnetModule, unityModule, netcodeModule);
445+
}
446+
}
447+
448+
return (dotnetModule, unityModule, netcodeModule);
449+
}
383450
}
384451
}

com.unity.netcode.gameobjects/Editor/CodeGen/INetworkMessageILPP.cs

Lines changed: 91 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.IO;
33
using System.Linq;
44
using System.Collections.Generic;
5-
using System.Reflection;
65
using Mono.Cecil;
76
using Mono.Cecil.Cil;
87
using Mono.Cecil.Rocks;
@@ -17,8 +16,7 @@ internal sealed class INetworkMessageILPP : ILPPInterface
1716
{
1817
public override ILPPInterface GetInstance() => this;
1918

20-
public override bool WillProcess(ICompiledAssembly compiledAssembly) =>
21-
compiledAssembly.Name == CodeGenHelpers.RuntimeAssemblyName;
19+
public override bool WillProcess(ICompiledAssembly compiledAssembly) => compiledAssembly.Name == CodeGenHelpers.RuntimeAssemblyName;
2220

2321
private readonly List<DiagnosticMessage> m_Diagnostics = new List<DiagnosticMessage>();
2422

@@ -32,13 +30,28 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
3230
m_Diagnostics.Clear();
3331

3432
// read
35-
var assemblyDefinition = CodeGenHelpers.AssemblyDefinitionFor(compiledAssembly, out var resolver);
33+
var assemblyDefinition = CodeGenHelpers.AssemblyDefinitionFor(compiledAssembly, out m_AssemblyResolver);
3634
if (assemblyDefinition == null)
3735
{
3836
m_Diagnostics.AddError($"Cannot read assembly definition: {compiledAssembly.Name}");
3937
return null;
4038
}
4139

40+
// modules
41+
(m_DotnetModule, _, m_NetcodeModule) = CodeGenHelpers.FindBaseModules(assemblyDefinition, m_AssemblyResolver);
42+
43+
if (m_DotnetModule == null)
44+
{
45+
m_Diagnostics.AddError($"Cannot find .NET module: {CodeGenHelpers.DotnetModuleName}");
46+
return null;
47+
}
48+
49+
if (m_NetcodeModule == null)
50+
{
51+
m_Diagnostics.AddError($"Cannot find Netcode module: {CodeGenHelpers.NetcodeModuleName}");
52+
return null;
53+
}
54+
4255
// process
4356
var mainModule = assemblyDefinition.MainModule;
4457
if (mainModule != null)
@@ -91,6 +104,9 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
91104
return new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), m_Diagnostics);
92105
}
93106

107+
private ModuleDefinition m_DotnetModule;
108+
private ModuleDefinition m_NetcodeModule;
109+
private PostProcessorAssemblyResolver m_AssemblyResolver;
94110

95111
private MethodReference m_MessagingSystem_ReceiveMessage_MethodRef;
96112
private TypeReference m_MessagingSystem_MessageWithHandler_TypeRef;
@@ -105,63 +121,108 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
105121

106122
private bool ImportReferences(ModuleDefinition moduleDefinition)
107123
{
108-
m_MessagingSystem_MessageHandler_Constructor_TypeRef = moduleDefinition.ImportReference(typeof(MessagingSystem.MessageHandler).GetConstructors()[0]);
124+
TypeDefinition typeTypeDef = null;
125+
TypeDefinition listTypeDef = null;
126+
foreach (var dotnetTypeDef in m_DotnetModule.GetAllTypes())
127+
{
128+
if (typeTypeDef == null && dotnetTypeDef.Name == typeof(Type).Name)
129+
{
130+
typeTypeDef = dotnetTypeDef;
131+
continue;
132+
}
133+
134+
if (listTypeDef == null && dotnetTypeDef.Name == typeof(List<>).Name)
135+
{
136+
listTypeDef = dotnetTypeDef;
137+
continue;
138+
}
139+
}
140+
141+
TypeDefinition messageHandlerTypeDef = null;
142+
TypeDefinition messageWithHandlerTypeDef = null;
143+
TypeDefinition ilppMessageProviderTypeDef = null;
144+
TypeDefinition messagingSystemTypeDef = null;
145+
foreach (var netcodeTypeDef in m_NetcodeModule.GetAllTypes())
146+
{
147+
if (messageHandlerTypeDef == null && netcodeTypeDef.Name == nameof(MessagingSystem.MessageHandler))
148+
{
149+
messageHandlerTypeDef = netcodeTypeDef;
150+
continue;
151+
}
152+
153+
if (messageWithHandlerTypeDef == null && netcodeTypeDef.Name == nameof(MessagingSystem.MessageWithHandler))
154+
{
155+
messageWithHandlerTypeDef = netcodeTypeDef;
156+
continue;
157+
}
158+
159+
if (ilppMessageProviderTypeDef == null && netcodeTypeDef.Name == nameof(ILPPMessageProvider))
160+
{
161+
ilppMessageProviderTypeDef = netcodeTypeDef;
162+
continue;
163+
}
164+
165+
if (messagingSystemTypeDef == null && netcodeTypeDef.Name == nameof(MessagingSystem))
166+
{
167+
messagingSystemTypeDef = netcodeTypeDef;
168+
continue;
169+
}
170+
}
171+
172+
m_MessagingSystem_MessageHandler_Constructor_TypeRef = moduleDefinition.ImportReference(messageHandlerTypeDef.GetConstructors().First());
109173

110-
var messageWithHandlerType = typeof(MessagingSystem.MessageWithHandler);
111-
m_MessagingSystem_MessageWithHandler_TypeRef = moduleDefinition.ImportReference(messageWithHandlerType);
112-
foreach (var fieldInfo in messageWithHandlerType.GetFields())
174+
m_MessagingSystem_MessageWithHandler_TypeRef = moduleDefinition.ImportReference(messageWithHandlerTypeDef);
175+
foreach (var fieldDef in messageWithHandlerTypeDef.Fields)
113176
{
114-
switch (fieldInfo.Name)
177+
switch (fieldDef.Name)
115178
{
116179
case nameof(MessagingSystem.MessageWithHandler.MessageType):
117-
m_MessagingSystem_MessageWithHandler_MessageType_FieldRef = moduleDefinition.ImportReference(fieldInfo);
180+
m_MessagingSystem_MessageWithHandler_MessageType_FieldRef = moduleDefinition.ImportReference(fieldDef);
118181
break;
119182
case nameof(MessagingSystem.MessageWithHandler.Handler):
120-
m_MessagingSystem_MessageWithHandler_Handler_FieldRef = moduleDefinition.ImportReference(fieldInfo);
183+
m_MessagingSystem_MessageWithHandler_Handler_FieldRef = moduleDefinition.ImportReference(fieldDef);
121184
break;
122185
}
123186
}
124187

125-
var typeType = typeof(Type);
126-
foreach (var methodInfo in typeType.GetMethods())
188+
foreach (var methodDef in typeTypeDef.Methods)
127189
{
128-
switch (methodInfo.Name)
190+
switch (methodDef.Name)
129191
{
130192
case nameof(Type.GetTypeFromHandle):
131-
m_Type_GetTypeFromHandle_MethodRef = moduleDefinition.ImportReference(methodInfo);
193+
m_Type_GetTypeFromHandle_MethodRef = moduleDefinition.ImportReference(methodDef);
132194
break;
133195
}
134196
}
135197

136-
var ilppMessageProviderType = typeof(ILPPMessageProvider);
137-
foreach (var fieldInfo in ilppMessageProviderType.GetFields(BindingFlags.Static | BindingFlags.NonPublic))
198+
foreach (var fieldDef in ilppMessageProviderTypeDef.Fields)
138199
{
139-
switch (fieldInfo.Name)
200+
switch (fieldDef.Name)
140201
{
141202
case nameof(ILPPMessageProvider.__network_message_types):
142-
m_ILPPMessageProvider___network_message_types_FieldRef = moduleDefinition.ImportReference(fieldInfo);
203+
m_ILPPMessageProvider___network_message_types_FieldRef = moduleDefinition.ImportReference(fieldDef);
143204
break;
144205
}
145206
}
146207

147-
var listType = typeof(List<MessagingSystem.MessageWithHandler>);
148-
foreach (var methodInfo in listType.GetMethods())
208+
foreach (var methodDef in listTypeDef.Methods)
149209
{
150-
switch (methodInfo.Name)
210+
switch (methodDef.Name)
151211
{
152-
case nameof(List<MessagingSystem.MessageWithHandler>.Add):
153-
m_List_Add_MethodRef = moduleDefinition.ImportReference(methodInfo);
212+
case "Add":
213+
m_List_Add_MethodRef = methodDef;
214+
m_List_Add_MethodRef.DeclaringType = listTypeDef.MakeGenericInstanceType(messageWithHandlerTypeDef);
215+
m_List_Add_MethodRef = moduleDefinition.ImportReference(m_List_Add_MethodRef);
154216
break;
155217
}
156218
}
157219

158-
var messagingSystemType = typeof(MessagingSystem);
159-
foreach (var methodInfo in messagingSystemType.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
220+
foreach (var methodDef in messagingSystemTypeDef.Methods)
160221
{
161-
switch (methodInfo.Name)
222+
switch (methodDef.Name)
162223
{
163224
case k_ReceiveMessageName:
164-
m_MessagingSystem_ReceiveMessage_MethodRef = moduleDefinition.ImportReference(methodInfo);
225+
m_MessagingSystem_ReceiveMessage_MethodRef = moduleDefinition.ImportReference(methodDef);
165226
break;
166227
}
167228
}
@@ -217,10 +278,8 @@ private void CreateInstructionsToRegisterType(ILProcessor processor, List<Instru
217278
instructions.Add(processor.Create(OpCodes.Callvirt, m_List_Add_MethodRef));
218279
}
219280

220-
// Creates a static module constructor (which is executed when the module is loaded) that registers all the
221-
// message types in the assembly with MessagingSystem.
222-
// This is the same behavior as annotating a static method with [ModuleInitializer] in standardized
223-
// C# (that attribute doesn't exist in Unity, but the static module constructor still works)
281+
// Creates a static module constructor (which is executed when the module is loaded) that registers all the message types in the assembly with MessagingSystem.
282+
// This is the same behavior as annotating a static method with [ModuleInitializer] in standardized C# (that attribute doesn't exist in Unity, but the static module constructor still works).
224283
// https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.moduleinitializerattribute?view=net-5.0
225284
// https://web.archive.org/web/20100212140402/http://blogs.msdn.com/junfeng/archive/2005/11/19/494914.aspx
226285
private void CreateModuleInitializer(AssemblyDefinition assembly, List<TypeDefinition> networkMessageTypes)

com.unity.netcode.gameobjects/Editor/CodeGen/INetworkSerializableILPP.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
namespace Unity.Netcode.Editor.CodeGen
1212
{
13-
1413
internal sealed class INetworkSerializableILPP : ILPPInterface
1514
{
1615
public override ILPPInterface GetInstance() => this;

0 commit comments

Comments
 (0)