private static void PatchICall <T>(string name, out T original, T target) where T : MulticastDelegate { var originalPointer = IL2CPP.il2cpp_resolve_icall(name); if (originalPointer == IntPtr.Zero) { MelonLogger.Warning($"ICall {name} was not found, not patching"); original = null; return; } NativePatchUtils.NativePatch(originalPointer, out original, target, name); }
public static void DoPatch() { NativePatchUtils.NativePatch(typeof(ApiModel).GetMethods().Single(it => it.Name == nameof(ApiModel.SetApiFieldsFromJson) && it.GetParameters().Length == 2 && it.GetParameters()[0].ParameterType.GenericTypeArguments[1] == typeof(Il2CppSystem.Object)), out ourOriginalApiPopulate, ApiSnifferStatic); NativePatchUtils.NativePatch(typeof(ApiModel).GetMethods().Single(it => it.Name == nameof(ApiModel.SetApiFieldsFromJson) && it.GetParameters().Length == 2 && it.GetParameters()[0].ParameterType.GenericTypeArguments[1] != typeof(Il2CppSystem.Object)), out ourOriginalApiPopulateTokens, ApiSnifferStaticTokens); NativePatchUtils.NativePatch(ImageDownloaderClosureType.GetMethod(nameof(ImageDownloaderClosure ._DownloadImageInternal_b__0)) !, out ourOriginalOnDone, ImageSnifferPatch); }
public static void HookVrIkInit() { var vrikInitMethod = typeof(VRCVrIkController).GetMethod(nameof(VRCVrIkController .Method_Public_Virtual_Final_New_Boolean_VRC_AnimationController_Animator_VRCPlayer_Boolean_0)) !; NativePatchUtils.NativePatch(vrikInitMethod, out ourOriginalVrIkInit, VrIkInitReplacement); NativePatchUtils.NativePatch(typeof(IKSolverVR).GetMethod(nameof(IKSolverVR.VrcLateSolve)) !, out ourOriginalSolverVrLateUpdate, SolverVrLateUpdatePatch); NativePatchUtils.NativePatch(typeof(IKSolver).GetMethod(nameof(IKSolver.Update)) !, out ourOriginalSolverUpdate, SolverUpdatePatch); NativePatchUtils.NativePatch(typeof(IKSolverVR.Spine).GetMethod(nameof(IKSolverVR.Spine.SolvePelvis)) !, out ourOriginalSolvePelvis, SolvePelvisPatch); NativePatchUtils.NativePatch(typeof(IKSolverVR.Spine).GetMethod(nameof(IKSolverVR.Spine.Solve)) !, out ourOriginalSolveSpine, SolveSpinePatch); NativePatchUtils.NativePatch(typeof(IKSolverVR.Arm).GetMethod(nameof(IKSolverVR.Arm.VrcAvoidElbowClipping)) !, out ourOriginalElbowClipping, ElbowClippingPatch); NativePatchUtils.NativePatch(typeof(IKSolverVR.Leg).GetMethod(nameof(IKSolverVR.Leg.Solve)) !, out ourOriginalLegSolve, LegSolvePatch); }
public override void OnApplicationStart() { if (!CheckWasSuccessful || !MustStayTrue || MustStayFalse) { return; } AdvancedSafetySettings.RegisterSettings(); ClassInjector.RegisterTypeInIl2Cpp <SortingOrderHammerer>(); try { BundleVerifierMod.OnApplicationStart(HarmonyInstance); } catch (Exception ex) { MelonLogger.Error($"Error initializing Bundle Verifier: {ex}"); } var matchingMethods = typeof(AssetManagement) .GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).Where(it => it.Name.StartsWith("Method_Public_Static_Object_Object_Vector3_Quaternion_Boolean_Boolean_Boolean_") && it.GetParameters().Length == 6).ToList(); foreach (var matchingMethod in matchingMethods) { ObjectInstantiateDelegate originalInstantiateDelegate = null; ObjectInstantiateDelegate replacement = (assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer) => ObjectInstantiatePatch(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer, originalInstantiateDelegate); NativePatchUtils.NativePatch(matchingMethod, out originalInstantiateDelegate, replacement); } foreach (var nestedType in typeof(VRCAvatarManager).GetNestedTypes()) { var moveNext = nestedType.GetMethod("MoveNext"); if (moveNext == null) { continue; } var avatarManagerField = nestedType.GetProperties().SingleOrDefault(it => it.PropertyType == typeof(VRCAvatarManager)); if (avatarManagerField == null) { continue; } MelonDebug.Msg($"Patching UniTask type {nestedType.FullName}"); var fieldOffset = (int)IL2CPP.il2cpp_field_get_offset((IntPtr)UnhollowerUtils .GetIl2CppFieldInfoPointerFieldForGeneratedFieldAccessor(avatarManagerField.GetMethod) .GetValue(null)); unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(moveNext).GetValue(null); originalMethodPointer = XrefScannerLowLevel.JumpTargets(originalMethodPointer).First(); VoidDelegate originalDelegate = null; void TaskMoveNextPatch(IntPtr taskPtr, IntPtr nativeMethodInfo) { var avatarManager = *(IntPtr *)(taskPtr + fieldOffset - 16); using (new AvatarManagerCookie(new VRCAvatarManager(avatarManager))) originalDelegate(taskPtr, nativeMethodInfo); } var patchDelegate = new VoidDelegate(TaskMoveNextPatch); NativePatchUtils.NativePatch(originalMethodPointer, out originalDelegate, patchDelegate); } } ReaderPatches.ApplyPatches(); SceneManager.add_sceneLoaded(new Action <Scene, LoadSceneMode>((s, _) => { if (s.buildIndex == -1) { CanReadAudioMixers = false; CanReadBadFloats = false; MelonDebug.Msg("No reading audio mixers anymore"); } })); SceneManager.add_sceneUnloaded(new Action <Scene>(s => { if (s.buildIndex == -1) { // allow loading mixers from world assetbundles CanReadAudioMixers = true; CanReadBadFloats = true; MelonDebug.Msg("Can read audio mixers now"); } })); PortalHiding.OnApplicationStart(); AvatarHiding.OnApplicationStart(HarmonyInstance); FinalIkPatches.ApplyPatches(HarmonyInstance); if (MelonHandler.Mods.Any(it => it.Info.Name == "UI Expansion Kit")) { typeof(UiExpansionKitSupport).GetMethod(nameof(UiExpansionKitSupport.OnApplicationStart), BindingFlags.Static | BindingFlags.Public) !.Invoke(null, new object[0]); } }