Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save OneManMonkeySquad/959c26b7364fa67e971488940bfddcbe to your computer and use it in GitHub Desktop.
Save OneManMonkeySquad/959c26b7364fa67e971488940bfddcbe to your computer and use it in GitHub Desktop.
Unity ILPostProcessor Cecil
Name the asmdef of your patcher Unity.SOMETHING.Codegen
Then edit the asmdef to include
"references": [ "Unity.CompilationPipeline.Common.dll" ],
I had to use my own Mono.Cecil dlls in the patcher directory, somehow it should be possible to reference the Unity.Cecil.dll etc.
Then use some code like this (Note at RpcPostProcessor.Process does the actual work here):
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Mono.Cecil;
using Unity.CompilationPipeline.Common.ILPostProcessing;
public class Patch : ILPostProcessor {
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern void OutputDebugString(string message);
public override ILPostProcessor GetInstance() {
return new Patch();
}
public override bool WillProcess(ICompiledAssembly compiledAssembly) {
string name = compiledAssembly.Name;
if (name.StartsWith("Unity.") || name.StartsWith("UnityEngine.") || name.StartsWith("UnityEditor."))
return false;
if (!compiledAssembly.References.Any(r => r.EndsWith("Cube.Replication.dll")))
return false; // No reference to Replication
OutputDebugString($"{compiledAssembly.Name}: WillProcess");
return true;
}
public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) {
OutputDebugString($"{compiledAssembly.Name}: Start patching...");
var msgs = new System.Collections.Generic.List<Unity.CompilationPipeline.Common.Diagnostics.DiagnosticMessage>();
try {
using (var stream = new MemoryStream(compiledAssembly.InMemoryAssembly.PeData)) {
var resolver = new DefaultAssemblyResolver();
foreach (var path in compiledAssembly.References) {
var dir = Path.GetDirectoryName(path);
if (resolver.GetSearchDirectories().Contains(dir))
continue;
OutputDebugString($"{compiledAssembly.Name}: Search in {dir}");
resolver.AddSearchDirectory(dir);
}
var readerParameters = new ReaderParameters() {
AssemblyResolver = resolver,
};
using (var assembly = AssemblyDefinition.ReadAssembly(stream, readerParameters)) {
var rpcProcessor = new RpcPostProcessor(assembly.MainModule);
var anythingChanged = rpcProcessor.Process(assembly.MainModule);
if (!anythingChanged) {
OutputDebugString($"{compiledAssembly.Name}: NOTHING CHANGED");
return new ILPostProcessResult(compiledAssembly.InMemoryAssembly);
}
using (var outStream = new MemoryStream()) {
assembly.Write(outStream);
OutputDebugString($"{compiledAssembly.Name}: SUCCESS");
return new ILPostProcessResult(new InMemoryAssembly(outStream.ToArray(), compiledAssembly.InMemoryAssembly.PdbData), msgs);
}
}
}
} catch (System.Exception e) {
var msg = new Unity.CompilationPipeline.Common.Diagnostics.DiagnosticMessage();
msg.DiagnosticType = Unity.CompilationPipeline.Common.Diagnostics.DiagnosticType.Error;
msg.MessageData = e.Message;
msgs.Add(msg);
OutputDebugString($"{compiledAssembly.Name}: FAILED {e.Message}");
return new ILPostProcessResult(null, msgs);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment