private void Awake() { var detour = new NativeDetour(typeof(Resources).GetMethod(nameof(Resources.UnloadUnusedAssets)), typeof(ResourceUnloadOptimizations).GetMethod(nameof(RunUnloadUnusedAssets))); detour.Apply(); originalUnload = detour.GenerateTrampoline <Func <AsyncOperation> >(); }
internal static void InitHooks() { var detour = new NativeDetour( typeof(SurvivorCatalog).GetMethodCached("Init"), typeof(SurvivorAPI).GetMethodCached(nameof(Init))); detour.Apply(); }
public static AbstractPhysicalObject Orig_AbstractPhysicalObjectFromString(World world, string str) { // Generating a trampoline may cause a segfault apofsDetour.Undo(); AbstractPhysicalObject ret = SaveState.AbstractPhysicalObjectFromString(world, str); apofsDetour.Apply(); return(ret); }
protected override void Apply(IntPtr from) { var hookPtr = Marshal.GetFunctionPointerForDelegate(new PrintFDelegate(OnUnityLog)); var det = new NativeDetour(from, hookPtr, new NativeDetourConfig { ManualApply = true }); original = det.GenerateTrampoline <PrintFDelegate>(); det.Apply(); }
private static void InstallHooks() { var target = AccessTools.Method(typeof(Resources), nameof(Resources.UnloadUnusedAssets)); var replacement = AccessTools.Method(typeof(Hooks), nameof(Hooks.UnloadUnusedAssetsHook)); var detour = new NativeDetour(target, replacement); detour.Apply(); _originalUnload = detour.GenerateTrampoline <Func <AsyncOperation> >(); HarmonyWrapper.PatchAll(typeof(Hooks)); }
public static unsafe bool Refresh(void *target) { Stack <NativeDetour> detours = _GetDetours((long)target); if (detours.Count == 0) { return(false); } NativeDetour detour = detours.Peek(); detour.Apply(); return(true); }
internal static Func <T, TResult> PatchGetter <T, TResult>(string propertyToPatch, Func <T, TResult> replacementGetter) { BindingFlags baseFlags = BindingFlags.Public | BindingFlags.NonPublic; MethodInfo origGetter = typeof(TextAsset).GetProperty(propertyToPatch, baseFlags | BindingFlags.Instance)?.GetGetMethod(); if (origGetter is null) { throw new ArgumentException($"Unable to patch { propertyToPatch }. Property not found."); } NativeDetour detour = new NativeDetour(origGetter, replacementGetter.Method); detour.Apply(); Logger.Log(LogLevel.Debug, $"patched: {origGetter.ReturnType} {nameof(TextAsset)}.{origGetter.Name}()"); return(detour.GenerateTrampoline <Func <T, TResult> >()); }
public override void Apply() { // The process to patch native methods is as follows: // 1. Create a managed proxy method that calls NativeDetour's trampoline (we need to cache it // because we don't know the trampoline method when generating the DMD). // 2. Pass the proxy to the normal Harmony manipulator to apply prefixes, postfixes, transpilers, etc. // 3. NativeDetour the method to the managed proxy // 4. Cache the NativeDetour's trampoline (technically we wouldn't need to, this is just a workaround // for MonoMod's API. if (IsRunningOnDotNetCore) { Logger.Log(Logger.LogChannel.Warn, () => $"Patch target {Original.GetID()} is marked as extern. " + "Extern methods may not be patched because of inlining behaviour of coreclr (refer to https://github.com/dotnet/coreclr/pull/8263)." + "If you need to patch externs, consider using pure NativeDetour instead."); } var prevDmd = _dmd; _nativeDetour?.Dispose(); _dmd = GenerateManagedOriginal(); var ctx = new ILContext(_dmd.Definition); HarmonyManipulator.Manipulate(Original, Original.GetPatchInfo(), ctx); var target = _dmd.Generate(); _nativeDetour = new NativeDetour(Original, target, new NativeDetourConfig { ManualApply = true }); lock (TrampolineCache) { if (prevDmd != null) { TrampolineCache.Remove(prevDmd.GetHashCode()); } TrampolineCache[_dmd.GetHashCode()] = CreateDelegate(_trampolineDelegateType, _nativeDetour.GenerateTrampoline(_invokeTrampolineMethod)); } _nativeDetour.Apply(); }
internal static void InitHooks() { var detour = new NativeDetour( typeof(SurvivorCatalog).GetMethodCached("Init"), typeof(SurvivorAPI).GetMethodCached(nameof(Init))); detour.Apply(); On.RoR2.SurvivorCatalog.GetSurvivorDef += (orig, index) => GetSurvivorDef(index); // TODO: THIS IS A HOTFIX, WHY IS THE FIRST CHARACTERBODY NULL On.RoR2.UI.LogBook.LogBookController.BuildCategories += orig => { typeof(BodyCatalog).SetFieldValue("bodyPrefabBodyComponents", typeof(BodyCatalog) .GetFieldValue <CharacterBody[]>("bodyPrefabBodyComponents") .Where(x => x != null).ToArray()); return(orig()); }; }
internal static void InitHooks() { var detour = new NativeDetour(typeof(SurvivorCatalog).GetMethod("Init", BindingFlags.NonPublic | BindingFlags.Static), typeof(SurvivorAPI).GetMethod(nameof(Init), BindingFlags.Public | BindingFlags.Static)); detour.Apply(); On.RoR2.SurvivorCatalog.GetSurvivorDef += (orig, survivorIndex) => { //orig is the original method and SurvivorIndex is the variable that is given to the original GetSurvivorDef if (survivorIndex < 0 || (int)survivorIndex > SurvivorDefinitions.Count) { return(null); } return(SurvivorDefinitions[(int)survivorIndex]); //by never doing orig(), the original method is never executed whenever it's called, effectively being replaced }; }
public static void Install() { if (_applied) { return; } new Hook(AccessTools.Method(AccessTools.Inner(typeof(ILHook), "Context"), "Refresh"), AccessTools.Method(typeof(StackTraceFixes), nameof(OnILChainRefresh))).Apply(); var nat = new NativeDetour(AccessTools.Method(typeof(Assembly), nameof(Assembly.GetExecutingAssembly)), AccessTools.Method(typeof(StackTraceFixes), nameof(GetAssemblyFix))); nat.Apply(); _realGetAss = nat.GenerateTrampoline <Func <Assembly> >(); new Hook(AccessTools.Method(typeof(StackFrame), nameof(StackFrame.GetMethod)), AccessTools.Method(typeof(StackTraceFixes), nameof(GetMethodFix))).Apply(); _applied = true; }
/// <inheritdoc /> public override MethodBase DetourTo(MethodBase replacement) { nativeDetour?.Dispose(); nativeDetour = new NativeDetour(Original, replacement, new NativeDetourConfig { ManualApply = true }); lock (TrampolineCache) { if (currentOriginal >= 0) { TrampolineCache.Remove(currentOriginal); } currentOriginal = newOriginal; TrampolineCache[currentOriginal] = CreateDelegate(trampolineDelegateType, nativeDetour.GenerateTrampoline(invokeTrampolineMethod)); } nativeDetour.Apply(); return(replacement); }
internal static void InitHooks() { ResourcesLoadDetour = new NativeDetour( typeof(Resources).GetMethod("Load", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string), typeof(Type) }, null), typeof(ResourcesAPI).GetMethod(nameof(OnResourcesLoad), BindingFlags.Static | BindingFlags.NonPublic) ); _origLoad = ResourcesLoadDetour.GenerateTrampoline <d_ResourcesLoad>(); ResourcesLoadDetour.Apply(); ResourcesLoadAsyncDetour = new NativeDetour( typeof(Resources).GetMethod("LoadAsyncInternal", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(string), typeof(Type) }, null), typeof(ResourcesAPI).GetMethod(nameof(OnResourcesLoadAsync), BindingFlags.Static | BindingFlags.NonPublic) ); _origResourcesLoadAsync = ResourcesLoadAsyncDetour.GenerateTrampoline <d_ResourcesAsyncLoad>(); ResourcesLoadAsyncDetour.Apply(); ResourcesLoadAllDetour = new NativeDetour( typeof(Resources).GetMethod("LoadAll", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string), typeof(Type) }, null), typeof(ResourcesAPI).GetMethod(nameof(OnResourcesLoadAll), BindingFlags.Static | BindingFlags.NonPublic) ); _origLoadAll = ResourcesLoadAllDetour.GenerateTrampoline <d_ResourcesLoadAll>(); ResourcesLoadAllDetour.Apply(); }