source: binary-improvements/assembly-patcher/Main.cs@ 116

Last change on this file since 116 was 115, checked in by alloc, 10 years ago

Fixes: Changed to a single solution for both patcher + fixes

File size: 5.0 KB
RevLine 
[73]1using System;
[107]2using System.Collections.Generic;
[73]3using System.Reflection;
4using Mono.Cecil;
5using Mono.Cecil.Cil;
6
7namespace dtdfixer
8{
9 class MainClass
10 {
11 public static void Main (string[] args)
12 {
13 ModuleDefinition module = ModuleDefinition.ReadModule ("Assembly-CSharp.dll");
[93]14
15 TypeDefinition type = module.GetType ("GameManager");
16 if (isPatched (type)) {
[107]17 Console.WriteLine ("Assembly already patched");
[93]18 return;
19 }
20 markTypePatched (module, type);
21
[107]22 consoleOutputPatch (module);
[73]23 telnetPatch (module);
[76]24 connectLogPatch (module);
[84]25 publicCommandPermissionsPatch (module);
[93]26 playerDataPatch (module);
[107]27
[115]28 module.Write ("Assembly-CSharp.patched.dll");
[73]29 Console.WriteLine ("Done");
[107]30
[73]31 }
32
[107]33 private static void consoleOutputPatch (ModuleDefinition module)
34 {
35 TypeDefinition type = module.GetType ("ConsoleSdtd");
36 replaceMethod (type, "ExecuteCmdFromClient", true, 3, typeof(ConsoleOutputSeparator).GetMethod ("C_ExecuteCmdFromClient"));
37 addHook (type, "Run", true, 0, true, typeof(ConsoleOutputSeparator).GetMethod ("C_Run"));
38 replaceMethod (type, "SendResult", true, 1, typeof(ConsoleOutputSeparator).GetMethod ("C_SendResult"));
39 }
40
[93]41 private static void playerDataPatch (ModuleDefinition module)
42 {
43 TypeDefinition type = module.GetType ("GameManager");
44 addHook (type, "SavePlayerData", true, 2, true, typeof(PlayerDataStuff).GetMethod ("GM_SavePlayerData"));
[107]45 addHook (type, "Awake", true, 0, true, typeof(CommandExtensions).GetMethod ("InitCommandExtensions"));
[93]46 }
47
[84]48 private static void publicCommandPermissionsPatch (ModuleDefinition module)
49 {
50 TypeDefinition type = module.GetType ("AdminTools");
51 replaceMethod (type, "GetAllowedCommandsList", true, 1, typeof(AdminToolsStuff).GetMethod ("GetAllowedCommandsList"));
52 }
53
[75]54 private static void connectLogPatch (ModuleDefinition module)
55 {
56 TypeDefinition type = module.GetType ("GameManager");
[83]57 addHook (type, "RequestToSpawnPlayer", true, 5, true, typeof(AllocsLogFunctions).GetMethod ("RequestToSpawnPlayer"));
[75]58 }
59
[73]60 private static void telnetPatch (ModuleDefinition module)
61 {
62 TypeDefinition type = module.GetType ("NetTelnetServer");
[84]63 replaceMethod (type, ".ctor", false, 1, typeof(AllocsNetTelnetServer).GetMethod ("init"));
64 replaceMethod (type, "Disconnect", false, 0, typeof(AllocsNetTelnetServer).GetMethod ("Disconnect"));
65 replaceMethod (type, "SetConsole", false, 1, typeof(AllocsNetTelnetServer).GetMethod ("SetConsole"));
66 replaceMethod (type, "WriteToClient", false, 1, typeof(AllocsNetTelnetServer).GetMethod ("WriteToClient"));
[73]67 }
68
69 private static void markTypePatched (ModuleDefinition module, TypeDefinition type)
70 {
71 type.Fields.Add (new FieldDefinition ("AllocsPatch", Mono.Cecil.FieldAttributes.Private | Mono.Cecil.FieldAttributes.SpecialName, module.Import (typeof(int))));
72 }
73
[76]74 private static void addHook (TypeDefinition type, string methodName, bool addThisRef, int opCount, bool atEnd, MethodBase targetMethod)
[73]75 {
76 foreach (MethodDefinition method in type.Methods) {
77 if (method.Name.Equals (methodName)) {
78 var il = method.Body.GetILProcessor ();
79 var call = il.Create (OpCodes.Call, method.Module.Import (targetMethod));
[76]80 if (atEnd) {
81 int insBefore = method.Body.Instructions.Count;
82 if (addThisRef)
83 il.Append (il.Create (OpCodes.Ldarg, 0));
84 for (int op = 0; op < opCount; op++) {
85 il.Append (il.Create (OpCodes.Ldarg, op + 1));
86 }
87 il.Append (call);
88 il.Remove (method.Body.Instructions [insBefore - 1]);
89 il.Append (il.Create (OpCodes.Ret));
90 } else {
91 var i = 0;
92 if (addThisRef)
93 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, 0));
94 for (int op = 0; op < opCount; op++) {
95 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
96 }
97 il.InsertBefore (method.Body.Instructions [i++], call);
[73]98 }
[107]99 return;
[75]100 }
101 }
[107]102 Console.WriteLine ("ERROR: Did not find " + type.Name + "." + methodName + "()");
[75]103 }
104
[84]105 private static void replaceMethod (TypeDefinition type, string methodName, bool addThisRef, int opCount, MethodBase targetMethod)
[75]106 {
107 foreach (MethodDefinition method in type.Methods) {
108 if (method.Name.Equals (methodName)) {
109 var il = method.Body.GetILProcessor ();
110 var call = il.Create (OpCodes.Call, method.Module.Import (targetMethod));
111 var i = 0;
[84]112 if (addThisRef)
113 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, 0));
[75]114 for (int op = 0; op < opCount; op++) {
115 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
116 }
117 il.InsertBefore (method.Body.Instructions [i++], call);
[73]118 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ret));
[107]119 return;
[73]120 }
121 }
[107]122 Console.WriteLine ("ERROR: Did not find " + type.Name + "." + methodName + "()");
[73]123 }
124
125 private static bool isPatched (TypeDefinition type)
126 {
127 foreach (FieldDefinition fd in type.Fields) {
128 if (fd.Name.Equals ("AllocsPatch")) {
129 return true;
130 }
131 }
132 return false;
133 }
134 }
135}
Note: See TracBrowser for help on using the repository browser.