private static IntPtr ObjectInstantiatePatch(IntPtr assetPtr, Vector3 pos, Quaternion rot, byte allowCustomShaders, byte isUI, byte validate, IntPtr nativeMethodPointer, ObjectInstantiateDelegate originalInstantiateDelegate) { if (AvatarManagerCookie.CurrentManager == null || assetPtr == IntPtr.Zero) { return(originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer)); } var avatarManager = AvatarManagerCookie.CurrentManager; var vrcPlayer = avatarManager.field_Private_VRCPlayer_0; if (vrcPlayer == null) { return(originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer)); } if (vrcPlayer == VRCPlayer.field_Internal_Static_VRCPlayer_0) // never apply to self { return(originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer)); } var go = new Object(assetPtr).TryCast <GameObject>(); if (go == null) { return(originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer)); } var wasActive = go.activeSelf; go.SetActive(false); var result = originalInstantiateDelegate(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer); go.SetActive(wasActive); if (result == IntPtr.Zero) { return(result); } var instantiated = new GameObject(result); try { CleanAvatar(AvatarManagerCookie.CurrentManager, instantiated); } catch (Exception ex) { MelonLogger.LogError($"Exception when cleaning avatar: {ex}"); } return(result); }
public override void OnApplicationStart() { AdvancedSafetySettings.RegisterSettings(); 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) { unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(matchingMethod).GetValue(null); ObjectInstantiateDelegate originalInstantiateDelegate = null; ObjectInstantiateDelegate replacement = (assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer) => ObjectInstantiatePatch(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer, originalInstantiateDelegate); ourPinnedDelegates.Add(replacement); MelonUtils.NativeHookAttach((IntPtr)(&originalMethodPointer), Marshal.GetFunctionPointerForDelegate(replacement)); originalInstantiateDelegate = Marshal.GetDelegateForFunctionPointer <ObjectInstantiateDelegate>(originalMethodPointer); } } unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumA).GetMethod( nameof(AMEnumA.MoveNext))) .GetValue(null); MelonUtils.NativeHookAttach((IntPtr)(&originalMethodPointer), typeof(AdvancedSafetyMod).GetMethod(nameof(MoveNextPatchA), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer()); ourMoveNextA = originalMethodPointer; } unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumB).GetMethod( nameof(AMEnumB.MoveNext))) .GetValue(null); MelonUtils.NativeHookAttach((IntPtr)(&originalMethodPointer), typeof(AdvancedSafetyMod).GetMethod(nameof(MoveNextPatchB), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer()); ourMoveNextB = originalMethodPointer; } unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumC).GetMethod( nameof(AMEnumC.MoveNext))) .GetValue(null); MelonUtils.NativeHookAttach((IntPtr)(&originalMethodPointer), typeof(AdvancedSafetyMod).GetMethod(nameof(MoveNextPatchC), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer()); ourMoveNextC = originalMethodPointer; } unsafe { var originalMethodInfo = (Il2CppMethodInfo *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumB).GetMethod( nameof(AMEnumB.MoveNext))) .GetValue(null); var methodInfoCopy = (Il2CppMethodInfo *)Marshal.AllocHGlobal(Marshal.SizeOf <Il2CppMethodInfo>()); * methodInfoCopy = *originalMethodInfo; ourInvokeMethodInfo = (IntPtr)methodInfoCopy; } foreach (ProcessModule module in Process.GetCurrentProcess().Modules) { if (!module.FileName.Contains("UnityPlayer")) { continue; } // ProduceHelper<AudioMixer,0>::Produce, thanks to Ben for finding an adjacent method ourAudioMixerReadPointer = module.BaseAddress + 0x4997C0; var patchDelegate = new AudioMixerReadDelegate(AudioMixerReadPatch); ourPinnedDelegates.Add(patchDelegate); unsafe { fixed(IntPtr *mixerReadAddress = &ourAudioMixerReadPointer) MelonUtils.NativeHookAttach((IntPtr)mixerReadAddress, Marshal.GetFunctionPointerForDelegate(patchDelegate)); ourAudioMixerReadDelegate = Marshal.GetDelegateForFunctionPointer <AudioMixerReadDelegate>(ourAudioMixerReadPointer); } break; } SceneManager.add_sceneLoaded(new Action <Scene, LoadSceneMode>((s, _) => { if (s.buildIndex == -1) { ourCanReadAudioMixers = 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 ourCanReadAudioMixers = true; MelonDebug.Msg("Can read audio mixers now"); } })); PortalHiding.OnApplicationStart(); AvatarHiding.OnApplicationStart(Harmony); if (MelonHandler.Mods.Any(it => it.Info.SystemType.Name == nameof(UiExpansionKitMod))) { typeof(UiExpansionKitSupport).GetMethod(nameof(UiExpansionKitSupport.OnApplicationStart), BindingFlags.Static | BindingFlags.Public) !.Invoke(null, new object[0]); } }
public override void OnApplicationStart() { AdvancedSafetySettings.RegisterSettings(); 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) { unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(matchingMethod).GetValue(null); ObjectInstantiateDelegate originalInstantiateDelegate = null; ObjectInstantiateDelegate replacement = (assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer) => ObjectInstantiatePatch(assetPtr, pos, rot, allowCustomShaders, isUI, validate, nativeMethodPointer, originalInstantiateDelegate); ourPinnedDelegates.Add(replacement); Imports.Hook((IntPtr)(&originalMethodPointer), Marshal.GetFunctionPointerForDelegate(replacement)); originalInstantiateDelegate = Marshal.GetDelegateForFunctionPointer <ObjectInstantiateDelegate>(originalMethodPointer); } } unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumA).GetMethod( nameof(AMEnumA.MoveNext))) .GetValue(null); Imports.Hook((IntPtr)(&originalMethodPointer), typeof(AdvancedSafetyMod).GetMethod(nameof(MoveNextPatchA), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer()); ourMoveNextA = originalMethodPointer; } unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumB).GetMethod( nameof(AMEnumB.MoveNext))) .GetValue(null); Imports.Hook((IntPtr)(&originalMethodPointer), typeof(AdvancedSafetyMod).GetMethod(nameof(MoveNextPatchB), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer()); ourMoveNextB = originalMethodPointer; } unsafe { var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumC).GetMethod( nameof(AMEnumC.MoveNext))) .GetValue(null); Imports.Hook((IntPtr)(&originalMethodPointer), typeof(AdvancedSafetyMod).GetMethod(nameof(MoveNextPatchC), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer()); ourMoveNextC = originalMethodPointer; } unsafe { var originalMethodInfo = (Il2CppMethodInfo *)(IntPtr)UnhollowerUtils .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(AMEnumB).GetMethod( nameof(AMEnumB.MoveNext))) .GetValue(null); var methodInfoCopy = (Il2CppMethodInfo *)Marshal.AllocHGlobal(Marshal.SizeOf <Il2CppMethodInfo>()); * methodInfoCopy = *originalMethodInfo; ourInvokeMethodInfo = (IntPtr)methodInfoCopy; } PortalHiding.OnApplicationStart(); AvatarHiding.OnApplicationStart(harmonyInstance); if (MelonHandler.Mods.Any(it => it.Info.SystemType.Name == nameof(UiExpansionKitMod))) { typeof(UiExpansionKitSupport).GetMethod(nameof(UiExpansionKitSupport.OnApplicationStart), BindingFlags.Static | BindingFlags.Public) !.Invoke(null, new object[0]); } }
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]); } }