Skip to content

Commit 485da56

Browse files
Merge pull request #16 from EvaisaDev/dev
Fix issue with injected IL
2 parents 2b0e728 + 9f50736 commit 485da56

File tree

6 files changed

+82
-33
lines changed

6 files changed

+82
-33
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[submodule "submodules/com.unity.netcode.gameobjects"]
22
path = submodules/com.unity.netcode.gameobjects
33
url = https://github.com/Unity-Technologies/com.unity.netcode.gameobjects
4-
branch = release/1.5.2
4+
branch = release/1.5.2
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Collections.Generic;
2+
using System.CommandLine;
3+
using System.CommandLine.Parsing;
4+
using System.IO;
5+
6+
namespace NetcodePatcher.Cli.Extensions;
7+
8+
public static class NoUncArgumentExtension
9+
{
10+
public static Argument<FileSystemInfo> NoUnc(this Argument<FileSystemInfo> argument)
11+
{
12+
argument.AddValidator(IsNotUnc);
13+
return argument;
14+
}
15+
16+
public static Argument<T> NoUnc<T>(this Argument<T> argument) where T : IEnumerable<FileSystemInfo>
17+
{
18+
argument.AddValidator(IsNotUnc);
19+
return argument;
20+
}
21+
22+
private static void IsNotUnc(ArgumentResult result)
23+
{
24+
foreach (var token in result.Tokens)
25+
{
26+
if (!token.Value.StartsWith(@"\\")) continue;
27+
result.ErrorMessage = "Argument cannot accept universal name specifiers - must provide local file/directory path.";
28+
return;
29+
}
30+
}
31+
}

NetcodePatcher.Cli/NetcodePatchCommand.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Diagnostics;
88
using System.Reflection;
99
using System.Threading.Tasks;
10+
using NetcodePatcher.Cli.Extensions;
1011
using Serilog;
1112
using Serilog.Events;
1213

@@ -19,8 +20,8 @@ public NetcodePatchCommand()
1920
Name = "netcode-patch";
2021
Description = "Netcode patch given assemblies";
2122

22-
Add(new Argument<FileSystemInfo>("plugin","Paths to patch folder/file") { Arity = ArgumentArity.ExactlyOne }.ExistingOnly());
23-
Add(new Argument<FileSystemInfo[]>("dependencies", "Paths to dependency folders/files") { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly());
23+
Add(new Argument<FileSystemInfo>("plugin","Paths to patch folder/file") { Arity = ArgumentArity.ExactlyOne }.ExistingOnly().NoUnc());
24+
Add(new Argument<FileSystemInfo[]>("dependencies", "Paths to dependency folders/files") { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly().NoUnc());
2425
Add(new Option<string?>(["--output", "-o"], "Output folder/file path").LegalFilePathsOnly());
2526
Add(new Option<bool>("--no-overwrite", "Sets output path to [assembly]_patched.dll, as opposed to renaming the original assembly").LegalFilePathsOnly());
2627
Add(new Option<bool>("--disable-parallel", "Don't publicize in parallel"));
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// https://github.com/adrianoc/cecilifier/blob/main/Cecilifier.Runtime/TypeHelpers.cs
2+
3+
using System.Linq;
4+
using Mono.Cecil;
5+
6+
namespace Cecilifier.Runtime;
7+
8+
public class TypeHelpers
9+
{
10+
public static MethodReference DefaultCtorFor(TypeReference type)
11+
{
12+
var resolved = type.Resolve();
13+
if (resolved == null)
14+
return null;
15+
16+
var ctor = resolved.Methods.SingleOrDefault(m => m.IsConstructor && m.Parameters.Count == 0 && !m.IsStatic);
17+
if (ctor == null)
18+
return DefaultCtorFor(resolved.BaseType);
19+
20+
return new MethodReference(".ctor", type.Module.TypeSystem.Void, type) { HasThis = true };
21+
}
22+
}

NetcodePatcher/CodeGen/ApplyPatchedAttributeILPP.cs

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4-
using System.Linq;
4+
using Cecilifier.Runtime;
55
using Mono.Cecil;
66
using Mono.Cecil.Cil;
77
using Mono.Cecil.Rocks;
@@ -25,7 +25,8 @@ public class ApplyPatchedAttributeILPP : ILPostProcessor
2525

2626
private readonly List<DiagnosticMessage> m_Diagnostics = [];
2727
private PostProcessorAssemblyResolver m_AssemblyResolver;
28-
28+
29+
// This function's implementation was written with the help of https://cecilifier.me/
2930
public override ILPostProcessResult? Process(ICompiledAssembly compiledAssembly)
3031
{
3132
if (!WillProcess(compiledAssembly)) return null;
@@ -39,41 +40,32 @@ public class ApplyPatchedAttributeILPP : ILPostProcessor
3940
m_Diagnostics.AddError($"Cannot read assembly definition: {compiledAssembly.Name}");
4041
return null;
4142
}
42-
43-
// do stuff
44-
var patchedAttributeDefinition = new TypeDefinition(
43+
44+
// Class : NetcodePatchedAttribute
45+
var cls_NetcodePatchedAttribute = new TypeDefinition(
4546
$"{assemblyDefinition.Name.Name}.{AttributeNamespaceSuffix}",
4647
AttributeName,
47-
TypeAttributes.NestedPrivate,
48+
TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.NotPublic,
4849
assemblyDefinition.MainModule.ImportReference(typeof(Attribute))
4950
);
50-
51-
var attributeUsageAttributeConstructor =
52-
assemblyDefinition.MainModule.ImportReference(
53-
typeof(AttributeUsageAttribute).GetConstructor([typeof(AttributeTargets)])
54-
);
55-
var attributeUsageAttribute = new CustomAttribute(attributeUsageAttributeConstructor);
56-
attributeUsageAttribute.ConstructorArguments.Add(
57-
new CustomAttributeArgument(assemblyDefinition.MainModule.ImportReference(typeof(AttributeTargets)), AttributeTargets.Assembly)
58-
);
59-
patchedAttributeDefinition.CustomAttributes.Add(attributeUsageAttribute);
51+
assemblyDefinition.MainModule.Types.Add(cls_NetcodePatchedAttribute);
6052

61-
var methodAttributes = MethodAttributes.Assembly | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
62-
var method = new MethodDefinition(".ctor", methodAttributes, assemblyDefinition.MainModule.TypeSystem.Void);
63-
method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
64-
var baseCtorReference = new MethodReference(".ctor", assemblyDefinition.MainModule.TypeSystem.Void, patchedAttributeDefinition.BaseType){HasThis = true};
65-
method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, baseCtorReference));
66-
method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
67-
patchedAttributeDefinition.Methods.Add(method);
53+
// Add AttributeUsage(AttributeTargets.Assembly) to NetcodePatchedAttribute
54+
var attr_AttributeUsage = new CustomAttribute(assemblyDefinition.MainModule.ImportReference(typeof(AttributeUsageAttribute).GetConstructor([typeof(AttributeTargets)])));
55+
attr_AttributeUsage.ConstructorArguments.Add(new CustomAttributeArgument(assemblyDefinition.MainModule.ImportReference(typeof(AttributeTargets)), 4));
56+
cls_NetcodePatchedAttribute.CustomAttributes.Add(attr_AttributeUsage);
6857

69-
assemblyDefinition.MainModule.Types.Add(patchedAttributeDefinition);
58+
// Method : NetcodePatchedAttribute.ctor
59+
var ctor_NetcodePatchedAttribute = new MethodDefinition(".ctor", MethodAttributes.Assembly | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, assemblyDefinition.MainModule.TypeSystem.Void);
60+
cls_NetcodePatchedAttribute.Methods.Add(ctor_NetcodePatchedAttribute);
61+
ctor_NetcodePatchedAttribute.Body.InitLocals = true;
62+
var il_ctor_NetcodePatchedAttribute = ctor_NetcodePatchedAttribute.Body.GetILProcessor();
63+
il_ctor_NetcodePatchedAttribute.Emit(OpCodes.Ldarg_0);
64+
il_ctor_NetcodePatchedAttribute.Emit(OpCodes.Call, assemblyDefinition.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(cls_NetcodePatchedAttribute.BaseType)));
65+
il_ctor_NetcodePatchedAttribute.Emit(OpCodes.Ret);
7066

71-
var attributeConstructor = assemblyDefinition.MainModule
72-
.ImportReference(patchedAttributeDefinition)
73-
.Resolve()
74-
.GetConstructors()
75-
.First();
76-
var attribute = new CustomAttribute(attributeConstructor);
67+
// Add NetcodePatchedAttribute to assembly definition
68+
var attribute = new CustomAttribute(assemblyDefinition.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(cls_NetcodePatchedAttribute)));
7769
assemblyDefinition.CustomAttributes.Add(attribute);
7870

7971
// write

NetcodePatcher/CodeGen/ILPostProcessorFromFile.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ public static void ILPostProcessFile(string assemblyPath, string outputPath, str
7676

7777
ILPostProcessResult result = ilpp.Process(assembly);
7878

79+
if (result is null)
80+
return assemblyToApplyProcessTo;
81+
7982
// handle the error messages like Unity would
8083
foreach (DiagnosticMessage message in result.Diagnostics)
8184
{

0 commit comments

Comments
 (0)