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

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

fixes

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