public static void DumpTypesUsedBy(this MethodBase methodBase) { if (methodBase == null) { return; } MelonLogger.Msg("Types used by method: " + methodBase.Name); HashSet <string> usedTypes = new HashSet <string>(); foreach (XrefInstance instance in XrefScanner.UsedBy(methodBase)) { if (instance.Type == XrefType.Method) { var resolved = instance.TryResolve(); if (resolved == null) { continue; } if (usedTypes.Contains(resolved.DeclaringType?.ToString())) { continue; } usedTypes.Add(resolved.DeclaringType?.ToString()); MelonLogger.Msg(resolved.DeclaringType?.ToString()); } } }
public static void ReloadAllAvatars(bool excludeSelf) { // xref yoinked from https://github.com/loukylor/VRC-Mods/commit/11abd2a62caaae5d0f817e20a0f6852d632da6bb#diff-ba8a2891e08655e0e158ea852ef76bbcb1ea58fc831a6817875c5efa21fef610R84 (GPLv3) if (ourReloadAllAvatarsDelegate == null) { var targetMethod = typeof(VRCPlayer).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) .Single(it => it.Name.StartsWith("Method_Public_Void_Boolean_") && it.GetParameters().Length == 1 && it.GetParameters()[0].IsOptional && XrefScanner.UsedBy(it).Any(jt => { if (jt.Type != XrefType.Method) { return(false); } var m = jt.TryResolve(); if (m == null) { return(false); } return(m.DeclaringType == typeof(FeaturePermissionManager) && m.Name.StartsWith("Method_Public_Void_")); })); ourReloadAllAvatarsDelegate = (Action <VRCPlayer, bool>)Delegate.CreateDelegate(typeof(Action <VRCPlayer, bool>), targetMethod); } ourReloadAllAvatarsDelegate(VRCPlayer.field_Internal_Static_VRCPlayer_0, excludeSelf); }
internal static bool PatchMethods() { try { // Left room MethodInfo onLeftRoomMethod = typeof(NetworkManager).GetMethod( nameof(NetworkManager.OnLeftRoom), BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, Type.EmptyTypes, null); origOnLeftRoom = Patch <OnLeftRoom>(onLeftRoomMethod, GetDetour(nameof(OnLeftRoomPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch OnLeftRoom\n" + e.Message); return(false); } try { // Faded to and joined and initialized room MethodInfo fadeMethod = typeof(VRCUiManager).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).First( m => m.Name.StartsWith("Method_Public_Void_String_Single_Action_") && m.Name.IndexOf("PDM", StringComparison.OrdinalIgnoreCase) == -1 && m.GetParameters().Length == 3); origFadeTo = Patch <FadeTo>(fadeMethod, GetDetour(nameof(FadeToPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch FadeTo\n" + e.Message); return(false); } if (Utilities.IsInVR) { try { // Fixes spinning issue // TL;DR Prevents the tracking manager from applying rotational force MethodInfo applyPlayerMotionMethod = typeof(VRCTrackingManager).GetMethods(BindingFlags.Public | BindingFlags.Static) .Where( m => m.Name.StartsWith("Method_Public_Static_Void_Vector3_Quaternion") && !m.Name.Contains("_PDM_")).First( m => XrefScanner.UsedBy(m).Any( xrefInstance => xrefInstance.Type == XrefType.Method && xrefInstance.TryResolve()?.ReflectedType ?.Equals(typeof(VRC_StationInternal)) == true)); origApplyPlayerMotion = Patch <ApplyPlayerMotion>(applyPlayerMotionMethod, GetDetour(nameof(ApplyPlayerMotionPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch ApplyPlayerMotion\n" + e.Message); return(false); } } return(true); }
public static bool CheckUsed(MethodInfo method, string methodName) { try { return(XrefScanner.UsedBy(method) .Where(instance => instance.TryResolve() != null && instance.TryResolve().Name.Contains(methodName)).Any()); } catch { } return(false); }
/// <summary> /// Checks the methods the given method is used by. /// Note: the methods passed into the predicate may be false. /// </summary> /// <param name="method">The method to check</param> /// <param name="predicate">The predicate to check the methods against</param> /// <returns>true if the predicate returned true any times, otherwise false</returns> public static bool CheckUsedBy(MethodBase method, Func <MethodBase, bool> predicate) { foreach (XrefInstance instance in XrefScanner.UsedBy(method)) { if (instance.Type == XrefType.Method && predicate.Invoke(instance.TryResolve())) { return(true); } } return(false); }
internal static void Patch(HarmonyInstance harmonyInstance) { try { // Left room harmonyInstance.Patch( typeof(NetworkManager).GetMethod(nameof(NetworkManager.OnLeftRoom), BindingFlags.Public | BindingFlags.Instance), postfix: GetPatch(nameof(LeftWorldPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch OnLeftRoom\n" + e.Message); } try { // Faded to and joined and initialized room IEnumerable <MethodInfo> fadeMethods = typeof(VRCUiManager).GetMethods() .Where( m => m.Name.StartsWith("Method_Public_Void_String_Single_Action_") && m.GetParameters().Length == 3); foreach (MethodInfo fadeMethod in fadeMethods) { harmonyInstance.Patch(fadeMethod, postfix: GetPatch(nameof(JoinedRoomPatch))); } } catch (Exception e) { MelonLogger.Error("Failed to patch FadeTo Initialized room\n" + e.Message); } if (Utilities.IsInVR) { try { // Fixes spinning issue // TL;DR Prevents the tracking manager from applying rotational force harmonyInstance.Patch( typeof(VRCTrackingManager).GetMethods(BindingFlags.Public | BindingFlags.Static) .Where(m => m.Name.StartsWith("Method_Public_Static_Void_Vector3_Quaternion") && !m.Name.Contains("_PDM_")) .First( m => XrefScanner.UsedBy(m).Any( xrefInstance => xrefInstance.Type == XrefType.Method && xrefInstance.TryResolve()?.ReflectedType?.Equals(typeof(VRC_StationInternal)) == true)), GetPatch(nameof(ApplyPlayerMotionPatch))); } catch (Exception e) { MelonLogger.Error("Failed to patch ApplyPlayerMotion\n" + e.Message); } } }
public static void ScanMethod(MethodInfo m) { MelonLogger.Msg($"Scanning: {m.FullDescription()}"); foreach (var instance in XrefScanner.XrefScan(m)) { try { if (instance.Type == XrefType.Global && instance.ReadAsObject() != null) { try { MelonLogger.Msg($" Found String: {instance.ReadAsObject().ToString()}"); } catch { } } else if (instance.Type == XrefType.Method && instance.TryResolve() != null) { try { MelonLogger.Msg($" Found Method: {instance.TryResolve().FullDescription()}"); } catch { } } } catch { } } foreach (var instance in XrefScanner.UsedBy(m)) { try { if (instance.Type == XrefType.Method && instance.TryResolve() != null) { try { MelonLogger.Msg($" Found Used By Method: {instance.TryResolve().FullDescription()}"); } catch { } } } catch { } } }
private static bool CheckUsed(MethodBase methodBase, string methodName) { if (!string.IsNullOrEmpty(methodName)) { try { return(XrefScanner.UsedBy(methodBase) .Where(instance => instance.TryResolve() != null && instance.TryResolve().Name.Contains(methodName)).Any()); } catch (Exception e) { MelonLogger.Error($"Failed to Xref CheckUsed:\n{e}"); } } return(false); }
/// <summary> /// Dumps the Xref information on a method. /// This is for DEBUG PURPOSES ONLY. /// </summary> /// <param name="method">The method to dump information on</param> public static void DumpXrefInfo(MethodBase method) { try { MelonLogger.Msg(ConsoleColor.Yellow, $"Scanning {method.Name}"); MelonLogger.Msg(ConsoleColor.Yellow, $"Checking UsedBy"); DumpScan(XrefScanner.UsedBy(method)); MelonLogger.Msg(ConsoleColor.Green, "Checking Using"); DumpScan(XrefScanner.XrefScan(method)); } catch (Exception ex) { MelonLogger.Error($"Failed while dumping {method.Name}:\n{ex}"); } }
public static void HookVrIkInit(HarmonyInstance harmony) { var vrikInitMethod = typeof(VRCVrIkController).GetMethod(nameof(VRCVrIkController .Method_Public_Virtual_Final_New_Boolean_VRC_AnimationController_Animator_VRCPlayer_Boolean_0)); harmony.Patch(vrikInitMethod, postfix: new HarmonyMethod(AccessTools.Method(typeof(VrIkHandling), nameof(VrikInitPatch)))); var methodThatChecksHipTracking = typeof(VRCVrIkController) .GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Single(it => XrefScanner.XrefScan(it).Any(jt => jt.Type == XrefType.Global && "Hip Tracking: Hip tracker found. tracking enabled." == jt.ReadAsObject()?.ToString())); var canSupportHipTrackingCandidates = XrefScanner.XrefScan(methodThatChecksHipTracking).Where(it => { if (it.Type != XrefType.Method) { return(false); } var resolved = it.TryResolve(); if (resolved == null || !resolved.IsStatic) { return(false); } if (!(resolved.DeclaringType == typeof(VRCTrackingManager) && resolved is MethodInfo mi && mi.ReturnType == typeof(bool) && resolved.GetParameters().Length == 0)) { return(false); } return(XrefScanner.UsedBy(resolved).Any(jt => jt.Type == XrefType.Method && jt.TryResolve().DeclaringType == typeof(QuickMenu))); }).ToList(); var canSupportHipTracking = canSupportHipTrackingCandidates.Single().TryResolve(); harmony.Patch(canSupportHipTracking, new HarmonyMethod(AccessTools.Method(typeof(VrIkHandling), nameof(SupportsHipTrackingPatch)))); }
static MethodInfo ms_applyStoredCalibration = null; // IKTweaks public static void ResolveMethods() { // void VRCTrackingManager.PrepareForCalibration() if (ms_prepareForCalibration == null) { var l_methods = typeof(VRCTrackingManager).GetMethods().Where(m => m.Name.StartsWith("Method_Public_Static_Void_") && (m.ReturnType == typeof(void)) && !m.GetParameters().Any() && XrefScanner.XrefScan(m).Where(x => (x.Type == XrefType.Global) && x.ReadAsObject().ToString().Contains("trying to calibrate")).Any() && XrefScanner.UsedBy(m).Where(x => (x.Type == XrefType.Method) && (x.TryResolve()?.DeclaringType == typeof(VRCFbbIkController))).Any() ); if (l_methods.Any()) { ms_prepareForCalibration = l_methods.First(); Main.Logger.Msg("VRCTrackingManager.PrepareForCalibration -> VRCTrackingManager." + ms_prepareForCalibration.Name); } else { Main.Logger.Warning("Can't resolve VRCTrackingManager.PrepareForCalibration"); } } // void VRCTracking.RestoreTrackingAfterCalibration() if (ms_restoreTrackingAfterCalibration == null) { var l_methods = typeof(VRCTrackingManager).GetMethods().Where(m => m.Name.StartsWith("Method_Public_Static_Void_") && (m.Name != ms_prepareForCalibration?.Name) && (m.ReturnType == typeof(void)) && !m.GetParameters().Any() && XrefScanner.UsedBy(m).Where(x => (x.Type == XrefType.Method) && (x.TryResolve()?.DeclaringType == typeof(VRCFbbIkController))).Any() ); if (l_methods.Any()) { ms_restoreTrackingAfterCalibration = l_methods.First(); Main.Logger.Msg("VRCTrackingManager.RestoreTrackingAfterCalibration -> VRCTrackingManager." + ms_restoreTrackingAfterCalibration.Name); } else { Main.Logger.Warning("Can't resolve VRCTrackingManager.RestoreTrackingAfterCalibration"); } } // void IKTweaks.CalibrationManager.Calibrate(GameObject avatarRoot) if (ms_calibrate == null) { foreach (MelonLoader.MelonMod l_mod in MelonLoader.MelonHandler.Mods) { if (l_mod.Info.Name == "IKTweaks") { Type l_cbType = null; l_mod.Assembly.GetTypes().DoIf(t => t.Name == "CalibrationManager", t => l_cbType = t); if (l_cbType != null) { ms_calibrate = l_cbType.GetMethod("Calibrate"); Main.Logger.Msg("IKTweaks.CalibrationManager.Calibrate " + ((ms_calibrate != null) ? "found" : "not found")); } break; } } } // Task IKTweaks.CalibrationManager.ApplyStoredCalibration(GameObject avatarRoot, string avatarId) if (ms_applyStoredCalibration == null) { foreach (MelonLoader.MelonMod l_mod in MelonLoader.MelonHandler.Mods) { if (l_mod.Info.Name == "IKTweaks") { Type l_cbType = null; l_mod.Assembly.GetTypes().DoIf(t => t.Name == "CalibrationManager", t => l_cbType = t); if (l_cbType != null) { ms_applyStoredCalibration = l_cbType.GetMethod("ApplyStoredCalibration", BindingFlags.NonPublic | BindingFlags.Static); Main.Logger.Msg("IKTweaks.CalibrationManager.ApplyStoredCalibration " + ((ms_applyStoredCalibration != null) ? "found" : "not found")); } break; } } } }
private static Transform GetTrackedTransform(VRCTracking.ID id) { ourGetTrackedTransform ??= (Func <VRCTracking.ID, Transform>)Delegate.CreateDelegate( typeof(Func <VRCTracking.ID, Transform>), typeof(VRCTrackingManager) .GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly).Single(it => it.Name.StartsWith("Method_Public_Static_Transform_ID_") && XrefScanner.UsedBy(it) .Any( jt => { var mr = jt.TryResolve(); return(mr?.DeclaringType == typeof(PedalOption_HudPosition) && mr.Name == "Update"); }))); return(ourGetTrackedTransform(id)); }