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

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

fixes

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