public static void Patch(DNContext context, string outputPath) { TerrariaPatcher.context = context; memRes = TerrariaPatcher.context.Resolver; TerrariaPatcher.context.PrimaryAssembly.Name = "Prism.Terraria"; TerrariaPatcher.context.PrimaryAssembly.ManifestModule.Name = TerrariaPatcher.context.PrimaryAssembly.Name + ".dll"; FindPlatform(); Publicify(); //AddInternalsVisibleToAttr(); RemoveConsoleWriteLineInWndProcHook(); ItemPatcher .Patch(); NpcPatcher .Patch(); ProjectilePatcher.Patch(); PlayerPatcher .Patch(); MountPatcher .Patch(); MainPatcher .Patch(); TilePatcher .Patch(); WorldFilePatcher .Patch(); RecipePatcher .Patch(); BuffPatcher .Patch(); // do other stuff here OptimizeAll(); // Newtonsoft.Json.dll, Steamworks.NET.dll and Ionic.Zip.CF.dll are required to write the assembly (and FNA and WindowsBase on mono, too) TerrariaPatcher.context.PrimaryAssembly.Write(outputPath); memRes = null; TerrariaPatcher.context = null; }
public static void Patch(DNContext context, string outputPath) { TerrariaPatcher.context = context; memRes = TerrariaPatcher.context.Resolver; TerrariaPatcher.context.PrimaryAssembly.Name = "Prism.Terraria"; TerrariaPatcher.context.PrimaryAssembly.ManifestModule.Name = TerrariaPatcher.context.PrimaryAssembly.Name + ".dll"; FindPlatform(); Publicify(); //AddInternalsVisibleToAttr(); RemoveConsoleWriteLineInWndProcHook(); ItemPatcher.Patch(); NpcPatcher.Patch(); ProjectilePatcher.Patch(); PlayerPatcher.Patch(); MountPatcher.Patch(); MainPatcher.Patch(); TilePatcher.Patch(); WorldFilePatcher.Patch(); RecipePatcher.Patch(); BuffPatcher.Patch(); // do other stuff here OptimizeAll(); // Newtonsoft.Json.dll, Steamworks.NET.dll and Ionic.Zip.CF.dll are required to write the assembly (and FNA and WindowsBase on mono, too) TerrariaPatcher.context.PrimaryAssembly.Write(outputPath); memRes = null; TerrariaPatcher.context = null; }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes ; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; AddZephyrFishBuffID(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; AddZephyrFishBuffID(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Recipe = memRes.GetType("Terraria.Recipe"); AddGroupRecipeField(); WrapMethods(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes ; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Recipe = memRes.GetType("Terraria.Recipe"); AddGroupRecipeField(); WrapMethods(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Proj = memRes.GetType("Terraria.Projectile"); WrapMethods(); AddFieldForBHandler(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes ; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Item = memRes.GetType("Terraria.Item"); WrapSetDefaults(); AddFieldForBHandler(); AddFieldForSound(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_WorldFile = memRes.GetType("Terraria.IO.WorldFile"); InjectSaveHook(); InjectLoadHook(); EnlargeFrameImportantArray(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Mount = memRes.GetType("Terraria.Mount"); WrapMethods(); AddFieldForBHandler(); Remove_FromFields(); RemoveTypeLimitations(); }
/*static bool IsGet2DArrCall(TypeReference arrayType, Instruction i) * { * var inner = arrayType.GetElementType(); * * if (i.OpCode.Code != Code.Call) * return false; * * var mtd = i.Operand as MethodReference; * * // for debugging * //if (mtd == null) * // return false; * //if (mtd.Name != "Get") * // return false; * //if (mtd.DeclaringType.FullName != arrayType.FullName) * // return false; * //if (!mtd.HasThis) * // return false; * //if (mtd.ReturnType != inner) * // return false; * //if (mtd.Parameters.Count != 2) * // return false; * //if (!mtd.Parameters.All(pd => pd.ParameterType == typeSys.Int32)) * // return false; * * //return true; * * return mtd != null && mtd.Name == "Get" && mtd.DeclaringType.FullName == arrayType.FullName && mtd.ReturnType == inner && !mtd.HasGenericParameters && mtd.Parameters.Count == 2 && mtd.Parameters.All(pd => pd.ParameterType == typeSys.Int32) && mtd.HasThis; * }*/ /*static void AddExtendedWallTypeField() * { * var wallTypeEx = new FieldDefinition("P_wallTypeEx", FieldAttributes.Assembly | FieldAttributes.Static, memRes.ReferenceOf(typeof(ushort[]))); * * var main_t = memRes.GetType("Terraria.Main"); * #region add field * { * typeDef_Tile.Fields.Add(wallTypeEx); * * // initialize in static ctor * var cb = typeDef_Tile.GetOrCreateStaticCtor().Body; * var cproc = cb.GetILProcessor(); * * var finalRet = cb.Instructions.Last(); * * cproc.InsertBefore(finalRet, Instruction.Create(OpCodes.Ldsfld, main_t.GetField("maxTilesX"))); * cproc.InsertBefore(finalRet, Instruction.Create(OpCodes.Ldsfld, main_t.GetField("maxTilesY"))); * cproc.InsertBefore(finalRet, Instruction.Create(OpCodes.Dup)); * cproc.InsertBefore(finalRet, Instruction.Create(OpCodes.Newarr, wallTypeEx.FieldType)); * cproc.InsertBefore(finalRet, Instruction.Create(OpCodes.Stsfld, wallTypeEx)); * } #endregion * #region add twodimentional getter * { * var getWallType = new MethodDefinition("GetWallType", MethodAttributes.Public | MethodAttributes.Static, typeSys.UInt16); * * getWallType.Parameters.Add(new ParameterDefinition("x", 0, typeSys.Int32)); * getWallType.Parameters.Add(new ParameterDefinition("y", 0, typeSys.Int32)); * * var gwproc = getWallType.Body.GetILProcessor(); * * gwproc.Emit(OpCodes.Ldsfld, wallTypeEx); * * // wallTypeEx[y * Main.maxTilesY + x] * gwproc.Emit(OpCodes.Ldarg_1); * //gwproc.Emit(OpCodes.Ldsfld, main_t.GetField("maxTilesY")); * gwproc.Emit(OpCodes.Ldc_I4, LARGEST_WLD_Y); * gwproc.Emit(OpCodes.Mul); * gwproc.Emit(OpCodes.Ldarg_0); * gwproc.Emit(OpCodes.Add); * gwproc.Emit(OpCodes.Ldelem_Ref); * gwproc.Emit(OpCodes.Ret); * * typeDef_Tile.Methods.Add(getWallType); * * // add an overload with a tile argument that ignores the tile, so the stack doesn't get messed up when using injected GetWallType(I) calls. * { * var getWallTypeI = new MethodDefinition("GetWallTypeI", MethodAttributes.Assembly | MethodAttributes.Static, typeSys.UInt16); * * getWallTypeI.Parameters.Add(new ParameterDefinition("tile", 0, typeSys.Object)); * getWallTypeI.Parameters.Add(new ParameterDefinition("x", 0, typeSys.Int32)); * getWallTypeI.Parameters.Add(new ParameterDefinition("y", 0, typeSys.Int32)); * * var gwiproc = getWallTypeI.Body.GetILProcessor(); * * gwiproc.Emit(OpCodes.Ldsfld, wallTypeEx); * * // wallTypeEx[y * Main.maxTilesY + x] * gwiproc.Emit(OpCodes.Ldarg_2); * //gwiproc.Emit(OpCodes.Ldsfld, main_t.GetField("maxTilesY")); * gwiproc.Emit(OpCodes.Ldc_I4, LARGEST_WLD_Y); * gwiproc.Emit(OpCodes.Mul); * gwiproc.Emit(OpCodes.Ldarg_1); * gwiproc.Emit(OpCodes.Add); * gwiproc.Emit(OpCodes.Ldelem_Ref); * gwiproc.Emit(OpCodes.Ret); * * typeDef_Tile.Methods.Add(getWallTypeI); * } * } #endregion * #region add twodimentional setter * { * var setWallType = new MethodDefinition("SetWallType", MethodAttributes.Public | MethodAttributes.Static, typeSys.Void); * * setWallType.Parameters.Add(new ParameterDefinition("x" , 0, typeSys. Int32)); * setWallType.Parameters.Add(new ParameterDefinition("y" , 0, typeSys. Int32)); * setWallType.Parameters.Add(new ParameterDefinition("value", 0, typeSys.UInt16)); * * var swproc = setWallType.Body.GetILProcessor(); * * swproc.Emit(OpCodes.Ldsfld, wallTypeEx); * * // wallTypeEx[y * Main.maxTilesY + x] * swproc.Emit(OpCodes.Ldarg_1); * //swproc.Emit(OpCodes.Ldsfld, main_t.GetField("maxTilesY")); * swproc.Emit(OpCodes.Ldc_I4, LARGEST_WLD_Y); * swproc.Emit(OpCodes.Mul); * swproc.Emit(OpCodes.Ldarg_0); * swproc.Emit(OpCodes.Add); * swproc.Emit(OpCodes.Ldarg_2); * swproc.Emit(OpCodes.Stelem_Ref); * swproc.Emit(OpCodes.Ret); * * typeDef_Tile.Methods.Add(setWallType); * * // add an overload with a tile argument that ignores the tile, so the stack doesn't get messed up when using injected SetWallType(I) calls. * { * var setWallTypeI = new MethodDefinition("SetWallTypeI", MethodAttributes.Assembly | MethodAttributes.Static, typeSys.Void); * * setWallTypeI.Parameters.Add(new ParameterDefinition("tile", 0, typeDef_Tile)); * setWallTypeI.Parameters.Add(new ParameterDefinition("x", 0, typeSys.Int32)); * setWallTypeI.Parameters.Add(new ParameterDefinition("y", 0, typeSys.Int32)); * setWallTypeI.Parameters.Add(new ParameterDefinition("value", 0, typeSys.UInt16)); * * var swb = setWallTypeI.Body; * * var swiproc = swb.GetILProcessor(); * * swiproc.Emit(OpCodes.Ldsfld, wallTypeEx); * * // wallTypeEx[y * Main.maxTilesY + x] * swiproc.Emit(OpCodes.Ldarg_2); * //swiproc.Emit(OpCodes.Ldsfld, main_t.GetField("maxTilesY")); * swiproc.Emit(OpCodes.Ldc_I4, LARGEST_WLD_Y); * swiproc.Emit(OpCodes.Mul); * swiproc.Emit(OpCodes.Ldarg_1); * swiproc.Emit(OpCodes.Add); * swiproc.Emit(OpCodes.Ldarg_3); * swiproc.Emit(OpCodes.Stelem_Ref); * swiproc.Emit(OpCodes.Ret); * * typeDef_Tile.Methods.Add(setWallTypeI); * } * } #endregion * }*/ /*static void ReplaceGetWallTypeCalls() * { * var gw = typeDef_Tile.GetMethod("GetWallTypeI"); // using the internal version * * var main_t = memRes.GetType("Terraria.Main"); * var main_tile = main_t.GetField("tile"); * var tile_wall = typeDef_Tile.GetField("wall"); * * foreach (var td in context.PrimaryAssembly.MainModule.Types) * foreach (var md in td.Methods) * { * if (!md.HasBody) * continue; * * var body = md.Body; * var ins = body.Instructions; * var proc = body.GetILProcessor(); * * for (int i = 0; i < ins.Count; i++) * { * var n = ins[i]; * * if (IsGet2DArrCall(main_tile.FieldType, n)) * { * n = n.Next; * * if (n == null) * continue; * * if (n.OpCode.Code == Code.Ldfld && n.Operand == tile_wall) * { * var p = ins[i].Previous; // shouldn't be null, tile array + indices are loaded on the IL stack * * proc.Remove(p.Next); * proc.Remove(n); * * proc.InsertAfter(p, Instruction.Create(OpCodes.Call, gw)); * * // rewire branch targets * foreach (var i_ in ins) * if (i_ != n && i_ != ins[i] && i_.Operand == ins[i]) * i_.Operand = p.Next; * * i--; * } * } * } * } * }*/ /*static void ReplaceSetWallTypeCalls() * { * var sw = typeDef_Tile.GetMethod("SetWallTypeI"); // using the internal version * * var main_t = memRes.GetType("Terraria.Main"); * var main_tile = main_t.GetField("tile"); * var tile_wall = typeDef_Tile.GetField("wall"); * * foreach (var td in context.PrimaryAssembly.MainModule.Types) * foreach (var md in td.Methods) * { * if (!md.HasBody) * continue; * * var body = md.Body; * var ins = body.Instructions; * var proc = body.GetILProcessor(); * * for (int i = 0; i < ins.Count; i++) * { * var n = ins[i]; * * if (n.OpCode.Code == Code.Stfld && n.Operand == tile_wall) * { * var p = ins[i].Previous; // shouldn't be null, tile array + indices are loaded on the IL stack * * proc.Remove(n); * * proc.InsertAfter(p, Instruction.Create(OpCodes.Call, sw)); * * // rewire branch targets * foreach (var i_ in ins) * if (i_ != n && i_.Operand == n) * i_.Operand = p.Next; * } * } * } * } * static void HideWallField() * { * var wall = typeDef_Tile.GetField("wall"); * * wall.Name = "P_wall"; * * wall.Attributes = FieldAttributes.Assembly; * }*/ #endregion internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Tile = memRes.GetType("Terraria.Tile"); ChangeFieldType(); ChangeLocalTypes(); //AddExtendedWallTypeField(); //ReplaceGetWallTypeCalls (); //ReplaceSetWallTypeCalls (); //HideWallField(); }
/// <summary> /// Replaces all method references with the specified reference within the specified context. /// </summary> /// <param name="context">The current <see cref="DNContext"/>.</param> /// <param name="targetRef">The <see cref="MethodReference"/> to replace.</param> /// <param name="newRef">The <see cref="MethodReference"/> to replace targetRef with.</param> /// <param name="exitRecursion">Excludes recursive method calls from the replacement operation (may have undesired consequences with recursive methods).</param> public static void ReplaceAllMethodRefs(this IMethod targetRef, IMethod newRef, DNContext context, bool exitRecursion = true) { foreach (var tDef in context.PrimaryAssembly.ManifestModule.Types) foreach (var mDef in tDef.Methods) { if (!mDef.HasBody) // abstract, runtime & external, etc continue; if (exitRecursion && mDef == newRef) // may have undesired consequences with recursive methods continue; foreach (var i in mDef.Body.Instructions) if (i.Operand is IMethod && comp.Equals(targetRef, (IMethod)i.Operand)) i.Operand = newRef; } }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes ; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Tile = memRes.GetType("Terraria.Tile"); ChangeFieldType (); ChangeLocalTypes(); //AddExtendedWallTypeField(); //ReplaceGetWallTypeCalls (); //ReplaceSetWallTypeCalls (); //HideWallField(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Player = memRes.GetType("Terraria.Player"); WrapMethods(); AddFieldForBHandler(); AddPlaceThingHook(); InsertSaveLoadHooks(); RemoveBuggyPlayerLoading(); RemoveStatCaps(); ReplaceUseSoundCalls(); FixOnEnterWorldBackingFieldName(); InjectMidUpdate(); InitBuffBHandlerArray(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes ; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_NPC = memRes.GetType("Terraria.NPC" ); WrapMethods(); AddFieldForBHandler(); AddFieldsForAudio(); InsertInitialize(); ReplaceSoundHitCalls(); ReplaceSoundKilledCalls(); InjectBuffEffectsCall(); InitBuffBHandlerArray(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_NPC = memRes.GetType("Terraria.NPC"); WrapMethods(); AddFieldForBHandler(); AddFieldsForAudio(); InsertInitialize(); ReplaceSoundHitCalls(); ReplaceSoundKilledCalls(); InjectBuffEffectsCall(); InitBuffBHandlerArray(); }
internal static void Patch() { context = TerrariaPatcher.context; memRes = TerrariaPatcher.memRes; typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; typeDef_Main = memRes.GetType("Terraria.Main"); WrapMethods(); RemoveVanillaNpcDrawLimitation(); FixOnEngineLoadField(); RemoveArmourDrawLimitations(); AddPreDrawHook(); AddOnUpdateKeyboardHook(); AddPostScreenClearHook(); //These are causing System.InvalidProgramExceptions so I'm just commenting them out (pls don't remove them) //AddIsChatAllowedHook(); //AddLocalChatHook(); }
public UnitOfWork(DNContext context) => _context = context;
static int Main(string[] args) { var toRem = new List <string>(); try { if (!ParseRuntimeArgs(args)) { return(1); } if (MsBuild) { Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } TerrariaExecutable = Path.GetFullPath(TerrariaExecutable); if (!File.Exists(TerrariaExecutable)) { Console.WriteLine("Terraria.exe not found. (full path: \"" + Path.GetFullPath(TerrariaExecutable) + "\")"); // the file is added in the .gitignore (and so is the patched file) if (MsBuild) { Console.WriteLine("In order to build Prism, you must place a copy of your own Terraria.exe file in the '." + Path.DirectorySeparatorChar /* be cross-platform */ + "References' directory."); } return(1); } var dir = Path.GetDirectoryName(TerrariaExecutable); if (!MsBuild) { Environment.CurrentDirectory = dir; } // just copy the files so the assembly resolving works, they'll be removed when it finished if (!MsBuild) { var fs = new[] { "Newtonsoft.Json", "Steamworks.NET", "Ionic.Zip.CF" }.Select(n => Path.Combine(dir, n + ".dll")); var ufs = new[] { "WindowsBase", "FNA" }.Select(n => Path.Combine(dir, n + ".dll")); foreach (var source in fs.Concat(IsWindows ? new string[0] : ufs)) { var target = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(source)); if (!File.Exists(target) /* don't do a useless copy (and worse, remove it afterwards, even when it could be needed later) */) { // unpack when file file does not exist if (!File.Exists(source)) { var dll = Assembly.GetExecutingAssembly().GetManifestResourceStream("Prism.TerrariaPatcher.RefDlls." + Path.GetFileName(source)); if (dll != null) { using (var fstr = File.OpenWrite(source)) { dll.CopyTo(fstr); fstr.Flush(true); } } } try // #15 { File.Copy(source, target, false); toRem.Add(target); } catch (IOException) { } // well f**k } } } var c = new DNContext(TerrariaExecutable); dir = Path.GetDirectoryName(PrismAssembly); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } // this will stop the build process if the patcher fails, because a reference in Prism.csproj will be missing if (MsBuild && File.Exists(PrismAssembly)) { File.Delete(PrismAssembly); } try { Console.Write("Patching, please wait... "); Patcher.Patch(c, PrismAssembly); } catch (Exception e) when(!Debugger.IsAttached) { Console.WriteLine("Something went wrong while patching " + Path.GetFileName(TerrariaExecutable) + ":"); Console.WriteLine(e); return(1); } Console.WriteLine("Patching finished."); return(0); } finally { if (!MsBuild) { Console.WriteLine("Press any key to exit..."); Console.ReadKey(true); } foreach (var s in toRem) { File.Delete(s); } } }
public static TypeDef CreateDelegate(this DNContext context, string @namespace, string name, TypeSig returnType, out MethodDef invoke, params TypeSig[] parameters) { var cResolver = context.Resolver; var typeSys = context.PrimaryAssembly.ManifestModule.CorLibTypes; var delegateType = new TypeDefUser(@namespace, name, cResolver.ReferenceOf(typeof(MulticastDelegate))); delegateType.Attributes = TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Sealed; var ctor = new MethodDefUser(".ctor", MethodSig.CreateInstance(typeSys.Void, typeSys.Object, typeSys.IntPtr), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); ctor.ImplAttributes |= MethodImplAttributes.Runtime; // param 0 is 'this' ctor.Parameters[1].CreateParamDef(); ctor.Parameters[1].ParamDef.Name = "object"; ctor.Parameters[2].CreateParamDef(); ctor.Parameters[2].ParamDef.Name = "method"; delegateType.Methods.Add(ctor); invoke = new MethodDefUser("Invoke", MethodSig.CreateInstance(returnType, parameters), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual); invoke.ImplAttributes |= MethodImplAttributes.Runtime; for (int i = 1; i <= parameters.Length; i++) { invoke.Parameters[i].CreateParamDef(); invoke.Parameters[i].ParamDef.Name = "arg" + (i - 1); } delegateType.Methods.Add(invoke); var beginInvoke = new MethodDefUser("BeginInvoke", MethodSig.CreateInstance(cResolver.ReferenceOf(typeof(IAsyncResult)).ToTypeSig(), parameters.Concat(new[] { cResolver.ReferenceOf(typeof(AsyncCallback)).ToTypeSig(), typeSys.Object }).ToArray()), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual); beginInvoke.ImplAttributes |= MethodImplAttributes.Runtime; for (int i = 0; i < parameters.Length; i++) { beginInvoke.Parameters[i + 1].CreateParamDef(); beginInvoke.Parameters[i + 1].ParamDef.Name = "arg" + i; } beginInvoke.Parameters[beginInvoke.Parameters.Count - 2].CreateParamDef(); beginInvoke.Parameters[beginInvoke.Parameters.Count - 2].ParamDef.Name = "callback"; beginInvoke.Parameters[beginInvoke.Parameters.Count - 1].CreateParamDef(); beginInvoke.Parameters[beginInvoke.Parameters.Count - 1].ParamDef.Name = "object"; delegateType.Methods.Add(beginInvoke); var endInvoke = new MethodDefUser("EndInvoke", MethodSig.CreateInstance(typeSys.Void, cResolver.ReferenceOf(typeof(IAsyncResult)).ToTypeSig()), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual); endInvoke.ImplAttributes |= MethodImplAttributes.Runtime; endInvoke.Parameters[1].CreateParamDef(); endInvoke.Parameters[1].ParamDef.Name = "result"; delegateType.Methods.Add(endInvoke); context.PrimaryAssembly.ManifestModule.Types.Add(delegateType); return(delegateType); }
public DNReflectionComparer(DNContext context) { c_wr = new WeakReference(context); }
public ProductRepository(DNContext context) => _context = context;
/// <summary> /// Replaces all method references with the specified reference within the specified context. /// </summary> /// <param name="context">The current <see cref="DNContext"/>.</param> /// <param name="targetRef">The <see cref="MethodReference"/> to replace.</param> /// <param name="newRef">The <see cref="MethodReference"/> to replace targetRef with.</param> /// <param name="exitRecursion">Excludes recursive method calls from the replacement operation (may have undesired consequences with recursive methods).</param> public static void ReplaceAllMethodRefs(this IMethod targetRef, IMethod newRef, DNContext context, bool exitRecursion = true) { foreach (var tDef in context.PrimaryAssembly.ManifestModule.Types) { foreach (var mDef in tDef.Methods) { if (!mDef.HasBody) // abstract, runtime & external, etc { continue; } if (exitRecursion && mDef == newRef) // may have undesired consequences with recursive methods { continue; } foreach (var i in mDef.Body.Instructions) { if (i.Operand is IMethod && comp.Equals(targetRef, (IMethod)i.Operand)) { i.Operand = newRef; } } } } }
/// <summary> /// Wraps a method using a fancy delegate. Replaces all references of the method with the wrapped one and creates an "On[MethodName]" hook which passes the method's parent type followed by the type parameters of the original method. /// </summary> /// <param name="context">The current Cecil context.</param> /// <param name="origMethod">The method to wrap.</param> public static void Wrap(this MethodDef method, DNContext context) { var delTypeName = DefDelTypeName(method); method.Wrap(context, delTypeName[0], delTypeName[1], "P_On" + GetOverloadedName(method)); }
/// <summary> /// Wraps a method using a fancy delegate. Replaces all references of the method with the wrapped one and creates an "On[MethodName]" hook which passes the method's parent type followed by the type parameters of the original method. /// </summary> /// <param name="context">The current Cecil context.</param> /// <param name="delegateNS">The namespace of the delegate type to create.</param> /// <param name="delegateTypeName">The name of the delegate type to create.</param> /// <param name="origMethod">The method to wrap.</param> public static void Wrap(this MethodDef origMethod, DNContext context, string delegateNS, string delegateTypeName, string fieldName) { MethodDef invokeDelegate; //SingletonTRArr[0] = origMethod.DeclaringType.ToTypeSig(); ////If anyone knows a better way to insert one element at the beginning of an array and scoot ////all the other elements down one index then go ahead and do it lol. I dunno how2array. var delegateArgs = origMethod.Parameters.Select(p => p.Type).ToArray(); var newDelegateType = context.CreateDelegate(delegateNS, delegateTypeName, origMethod.ReturnType, out invokeDelegate, delegateArgs); var newMethod = origMethod.ReplaceAndHook(invokeDelegate, origMethod, fieldName); // you're not special anymore! if ((origMethod.Attributes & MethodAttributes.SpecialName) != 0) origMethod.Attributes ^= MethodAttributes.SpecialName; if ((origMethod.Attributes & MethodAttributes.RTSpecialName) != 0) origMethod.Attributes ^= MethodAttributes.RTSpecialName; origMethod.ReplaceAllMethodRefs(newMethod, context); }
static int Main(string[] args) { var toRem = new List<string>(); try { if (!ParseRuntimeArgs(args)) return 1; if (MsBuild) Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); TerrariaExecutable = Path.GetFullPath(TerrariaExecutable); if (!File.Exists(TerrariaExecutable)) { Console.WriteLine("Terraria.exe not found. (full path: \"" + Path.GetFullPath(TerrariaExecutable) + "\")"); // the file is added in the .gitignore (and so is the patched file) if (MsBuild) Console.WriteLine("In order to build Prism, you must place a copy of your own Terraria.exe file in the '." + Path.DirectorySeparatorChar /* be cross-platform */ + "References' directory."); return 1; } var dir = Path.GetDirectoryName(TerrariaExecutable); if (!MsBuild) Environment.CurrentDirectory = dir; // just copy the files so the assembly resolving works, they'll be removed when it finished if (!MsBuild) { var fs = new[] { "Newtonsoft.Json", "Steamworks.NET", "Ionic.Zip.CF" }.Select(n => Path.Combine(dir, n + ".dll")); var ufs = new[] { "WindowsBase" , "FNA" }.Select(n => Path.Combine(dir, n + ".dll")); foreach (var source in fs.Concat(IsWindows ? new string[0] : ufs)) { var target = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(source)); if (!File.Exists(target) /* don't do a useless copy (and worse, remove it afterwards, even when it could be needed later) */) { // unpack when file file does not exist if (!File.Exists(source)) { var dll = Assembly.GetExecutingAssembly().GetManifestResourceStream("Prism.TerrariaPatcher.RefDlls." + Path.GetFileName(source)); if (dll != null) using (var fstr = File.OpenWrite(source)) { dll.CopyTo(fstr); fstr.Flush(true); } } try // #15 { File.Copy(source, target, false); toRem.Add(target); } catch (IOException) { } // well f**k } } } var c = new DNContext(TerrariaExecutable); dir = Path.GetDirectoryName(PrismAssembly); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); // this will stop the build process if the patcher fails, because a reference in Prism.csproj will be missing if (MsBuild && File.Exists(PrismAssembly)) File.Delete(PrismAssembly); try { Console.Write("Patching, please wait... "); Patcher.Patch(c, PrismAssembly); } catch (Exception e) when (!Debugger.IsAttached) { Console.WriteLine("Something went wrong while patching " + Path.GetFileName(TerrariaExecutable) + ":"); Console.WriteLine(e); return 1; } Console.WriteLine("Patching finished."); return 0; } finally { if (!MsBuild) { Console.WriteLine("Press any key to exit..."); Console.ReadKey(true); } foreach (var s in toRem) File.Delete(s); } }