Example #1
0
        /// <inheritdoc />
        public override DynamicMethodDefinition CopyOriginal()
        {
            var dmd = new DynamicMethodDefinition(Original);

            dmd.Definition.Name = "UnhollowedWrapper_" + dmd.Definition.Name;

            var cursor = new ILCursor(new ILContext(dmd.Definition));


            // Remove il2cpp_object_get_virtual_method

            if (cursor.TryGotoNext(x => x.MatchLdarg(0),
                                   x => x.MatchCall(typeof(UnhollowerBaseLib.IL2CPP), nameof(UnhollowerBaseLib.IL2CPP.Il2CppObjectBaseToPtr)),
                                   x => x.MatchLdsfld(out _),
                                   x => x.MatchCall(typeof(UnhollowerBaseLib.IL2CPP), nameof(UnhollowerBaseLib.IL2CPP.il2cpp_object_get_virtual_method))))
            {
                cursor.RemoveRange(4);
            }
            else
            {
                cursor.Goto(0)
                .GotoNext(x => x.MatchLdsfld(UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(Original)))
                .Remove();
            }

            // Replace original IL2CPPMethodInfo pointer with a modified one that points to the trampoline

            cursor
            .Emit(Mono.Cecil.Cil.OpCodes.Ldc_I8, ((IntPtr)modifiedNativeMethodInfo).ToInt64())
            .Emit(Mono.Cecil.Cil.OpCodes.Conv_I);

            return(dmd);
        }
Example #2
0
        public override void OnApplicationStart()
        {
            ModPrefs.RegisterCategory(SettingsCategory, "Sparkle Be Gone");

            ModPrefs.RegisterPrefBool(SettingsCategory, StartSparkleSetting, false, "Show start sparkle");
            ModPrefs.RegisterPrefBool(SettingsCategory, EndSparksSetting, false, "Show end sparks");
            ModPrefs.RegisterPrefBool(SettingsCategory, EndFlareSetting, true, "Show end flare");

            ModPrefs.RegisterPrefBool(SettingsCategory, RecolorSparksSetting, false, "Recolor sparks");
            ModPrefs.RegisterPrefBool(SettingsCategory, RecolorBeamsSetting, true, "Recolor beams");

            ModPrefs.RegisterPrefString(SettingsCategory, BeamColorSetting, "25 50 255 255", "Beam color (r g b a)");

            var method = typeof(VRCSpaceUiPointer).GetMethod(nameof(VRCSpaceUiPointer.LateUpdate), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            {
                using var stream    = Assembly.GetExecutingAssembly().GetManifestResourceStream("SparkleBeGone.sparklebegone");
                using var memStream = new MemoryStream((int)stream.Length);
                stream.CopyTo(memStream);
                var bundle = AssetBundle.LoadFromMemory_Internal(memStream.ToArray(), 0);
                myWhiteLaserTexture            = bundle.LoadAsset_Internal("Assets/SparkleBeGone/sniper_beam_white.png", Il2CppType.Of <Texture2D>()).Cast <Texture2D>();
                myWhiteLaserTexture.hideFlags |= HideFlags.DontUnloadUnusedAsset;
            }

            unsafe
            {
                var originalPointer = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method).GetValue(null);
                CompatHook((IntPtr)(&originalPointer), typeof(SparkleBeGoneMod).GetMethod(nameof(CursorLateUpdatePatch), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer());
                ourOriginalLateUpdate = Marshal.GetDelegateForFunctionPointer <VoidDelegate>(originalPointer);
            }

            MelonCoroutines.Start(InitThings());
        }
Example #3
0
        private static unsafe TDelegate Patch <TDelegate>(MethodBase originalMethod, IntPtr patchDetour)
        {
            IntPtr original = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(originalMethod).GetValue(null);

            MelonUtils.NativeHookAttach((IntPtr)(&original), patchDetour);
            return(Marshal.GetDelegateForFunctionPointer <TDelegate>(original));
        }
Example #4
0
        private void Init()
        {
            try
            {
                var methodField = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(Original);

                if (methodField == null)
                {
                    throw new Exception($"No IL2CPP equivalent found for {Original.FullDescription()}. The target might have been automatically generated by Unhollower (e.g. field accessor).");
                }

                // Get the native MethodInfo struct for the target method
                originalNativeMethodInfo = (Il2CppMethodInfo *)(IntPtr)methodField.GetValue(null);

                // Create a trampoline from the original target method

                var trampolinePtr = DetourGenerator.CreateTrampolineFromFunction(originalNativeMethodInfo->methodPointer, out _, out _);

                // Create a modified native MethodInfo struct to point towards the trampoline

                modifiedNativeMethodInfo = (Il2CppMethodInfo *)Marshal.AllocHGlobal(Marshal.SizeOf <Il2CppMethodInfo>());
                Marshal.StructureToPtr(*originalNativeMethodInfo, (IntPtr)modifiedNativeMethodInfo, false);

                modifiedNativeMethodInfo->methodPointer = trampolinePtr;
                isValid = true;
            }
            catch (Exception e)
            {
                DetourLogger.LogWarning($"Failed to init IL2CPP patch backend for {Original.FullDescription()}, using normal patch handlers: {e.Message}");
            }
        }
Example #5
0
        public static unsafe void RegisterType(Type type)
        {
            try
            {
                Lock.EnterUpgradeableReadLock();
                if (RegisteredTypes.Contains(type))
                {
                    return;
                }

                try
                {
                    Lock.EnterWriteLock();
                    RegisteredTypes.Add(type);

                    void ProcessMethod(MethodBase method)
                    {
                        if (method.IsGenericMethod || method.IsGenericMethodDefinition)
                        {
                            return;
                        }
                        if (method.GetMethodBody() == null)
                        {
                            return;
                        }
                        var pointerField = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method);

                        if (pointerField == null || pointerField.DeclaringType?.IsGenericTypeDefinition == true)
                        {
                            return;
                        }
                        MethodMap[*(IntPtr *)(IntPtr)pointerField.GetValue(null)] = method;
                    }

                    var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
                    foreach (var methodInfo in methods)
                    {
                        ProcessMethod(methodInfo);
                    }

                    var ctors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
                    foreach (var methodInfo in ctors)
                    {
                        ProcessMethod(methodInfo);
                    }
                }
                finally
                {
                    Lock.ExitWriteLock();
                }
            }
            finally
            {
                Lock.ExitUpgradeableReadLock();
            }
            if (type.BaseType != null)
            {
                RegisterType(type.BaseType);
            }
        }
        public static unsafe IEnumerable <XrefInstance> XrefScan(MethodBase methodBase)
        {
            var fieldValue = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodBase)?.GetValue(null);

            if (fieldValue == null)
            {
                return(Enumerable.Empty <XrefInstance>());
            }

            var cachedAttribute = methodBase.GetCustomAttribute <CachedScanResultsAttribute>(false);

            if (cachedAttribute == null)
            {
                XrefScanMetadataRuntimeUtil.CallMetadataInitForMethod(methodBase);

                return(XrefScanImpl(DecoderForAddress(*(IntPtr *)(IntPtr)fieldValue)));
            }

            if (cachedAttribute.XrefRangeStart == cachedAttribute.XrefRangeEnd)
            {
                return(Enumerable.Empty <XrefInstance>());
            }

            XrefScanMethodDb.CallMetadataInitForMethod(cachedAttribute);

            return(XrefScanMethodDb.CachedXrefScan(cachedAttribute).Where(it => it.Type == XrefType.Method || XrefGlobalClassFilter(it.Pointer)));
        }
Example #7
0
        public static unsafe void ApplyPatches()
        {
            try
            {
                // PDM's are scary:(
                MethodInfo avatarChangedMethod = typeof(VRCAvatarManager).GetMethods().FirstOrDefault(method => method.Name.StartsWith("Method_Private_Void_ApiAvatar_GameObject_Action_1_Boolean_"));

                IntPtr original = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(avatarChangedMethod).GetValue(null);
                MelonUtils.NativeHookAttach((IntPtr)(&original), typeof(ImmersiveTouch).GetMethod(nameof(ImmersiveTouch.OnAvatarChanged), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer());
                avatarChangedDelegate = Marshal.GetDelegateForFunctionPointer <AvatarChangedDelegate>(original);
            }
            catch (Exception e) { MelonLogger.Error($"Failed to patch: OnAvatarChanged\n{e}"); }

            try
            {
                IntPtr original = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(DynamicBone).GetMethod(nameof(DynamicBone.Method_Private_Void_Boolean_0))).GetValue(null);
                MelonUtils.NativeHookAttach((IntPtr)(&original), typeof(ImmersiveTouch).GetMethod(nameof(ImmersiveTouch.OnUpdateParticles), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer());
                updateParticlesDelegate = Marshal.GetDelegateForFunctionPointer <UpdateParticlesDelegate>(original);
            }
            catch (Exception e) { MelonLogger.Error($"Failed to patch: OnUpdateParticles\n{e}"); }

            try
            {
                IntPtr original = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(DynamicBoneCollider).GetMethod(nameof(DynamicBoneCollider.Method_Public_Void_byref_Vector3_Single_0))).GetValue(null);
                MelonUtils.NativeHookAttach((IntPtr)(&original), typeof(ImmersiveTouch).GetMethod(nameof(ImmersiveTouch.OnCollide), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer());
                collideDelegate = Marshal.GetDelegateForFunctionPointer <CollideDelegate>(original);
            }
            catch (Exception e) { MelonLogger.Error($"Failed to patch: OnCollide\n{e}"); }
        }
Example #8
0
 public static IntPtr Il2CppPtr(this MethodInfo methodInfo)
 {
     unsafe
     {
         return(*(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodInfo).GetValue(null));
     }
 }
Example #9
0
        public static void HookIntoSpawnData()
        {
            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(EnemyGroup).GetMethod(nameof(EnemyGroup.GetSpawnData)))
                                            .GetValue(null);

                FastNativeDetour.CreateAndApply(originalMethodPointer, HackyHooks.GetEnemySpawnDataPatch, out ourGetEnemySpawnData, CallingConvention.Cdecl);
            }
        }
Example #10
0
        public static void HookIntoChatMessages()
        {
            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(PlayerChatManager).GetMethod(nameof(PlayerChatManager.DoSendChatMessage)))
                                            .GetValue(null);

                FastNativeDetour.CreateAndApply(originalMethodPointer, HackyHooks.ChatMsgPatch, out ourChatDelegate, CallingConvention.Cdecl);
            }
        }
Example #11
0
        private static void ApplyPatches()
        {
            PatchICall("UnityEngine.Transform::" + nameof(Transform.set_position_Injected), out ourOriginalTransformSetter, nameof(SetTransformVectorPatch));
            PatchICall("UnityEngine.Transform::" + nameof(Transform.set_rotation_Injected), out ourOriginalTransformRotSetter, nameof(SetTransformQuaternionPatch));
            PatchICall("UnityEngine.Transform::" + nameof(Transform.SetPositionAndRotation_Injected), out ourOriginalTransformTwinSetter, nameof(SetTransformVectorQuaternionPatch));

            PatchICall("UnityEngine.Rigidbody::" + nameof(Rigidbody.set_position_Injected), out ourOriginalRigidbodyPosSetter, nameof(SetRigidbodyPosPatch));
            PatchICall("UnityEngine.Rigidbody::" + nameof(Rigidbody.set_rotation_Injected), out ourOriginalRigidbodyRotSetter, nameof(SetRigidbodyRotPatch));
            PatchICall("UnityEngine.Rigidbody::" + nameof(Rigidbody.MovePosition_Injected), out ourOriginalRigidbodyPosMove, nameof(SetRigidbodyPosMovePatch));
            PatchICall("UnityEngine.Rigidbody::" + nameof(Rigidbody.MoveRotation_Injected), out ourOriginalRigidbodyRotMove, nameof(SetRigidbodyRotMovePatch));
            PatchICall("UnityEngine.Rigidbody::" + nameof(Rigidbody.set_velocity_Injected), out ourOriginalRigidbodyVelSetter, nameof(SetRigidbodyVelPatch));
            PatchICall("UnityEngine.Rigidbody::" + nameof(Rigidbody.set_angularVelocity_Injected), out ourOriginalRigidbodyAvSetter, nameof(SetRigidbodyAvPatch));

            // These two were originally used to deserialize stuff from photon, but it seems like the vector one is not used anymore
            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(PhotonSerializers).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly).Single(it =>
                {
                    var parameters = it.GetParameters();
                    if (it.ReturnType != typeof(void) || parameters.Length != 3 || it.Name.Contains("_PDM_") || parameters[1].ParameterType != typeof(Vector3).MakeByRefType())
                    {
                        return(false);
                    }
                    return(true);
                }))
                                            .GetValue(null);

                Imports.Hook((IntPtr)(&originalMethodPointer), typeof(FinitizerMod).GetMethod(nameof(VectorPatch), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer());

                ourOriginalVectorMethod = Marshal.GetDelegateForFunctionPointer <VectorMethod>(originalMethodPointer);
            }

            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(PhotonSerializers).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly).Single(it =>
                {
                    var parameters = it.GetParameters();
                    if (it.ReturnType != typeof(void) || parameters.Length != 3 || it.Name.Contains("_PDM_") || parameters[1].ParameterType != typeof(Quaternion).MakeByRefType())
                    {
                        return(false);
                    }
                    return(true);
                }))
                                            .GetValue(null);

                Imports.Hook((IntPtr)(&originalMethodPointer), typeof(FinitizerMod).GetMethod(nameof(QuaternionPatch), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer());

                ourOriginalQuaternionMethod = Marshal.GetDelegateForFunctionPointer <QuaternionMethod>(originalMethodPointer);
            }

            MelonLogger.Log("Things patching complete");
        }
Example #12
0
        public static void OnApplicationStart()
        {
            if (File.Exists(BlockedAvatarsMakersFilePath))
            {
                ourBlockedAvatarAuthors.Clear();
                foreach (var it in File.ReadAllLines(BlockedAvatarsMakersFilePath, Encoding.UTF8))
                {
                    var split = it.Split(new[] { '͏', ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
                    if (split.Length == 2)
                    {
                        ourBlockedAvatarAuthors[split[0].Trim()] = split[1];
                    }
                }
            }

            if (File.Exists(BlockedAvatarsFilePath))
            {
                ourBlockedAvatars.Clear();
                foreach (var it in File.ReadAllLines(BlockedAvatarsFilePath, Encoding.UTF8))
                {
                    var split = it.Split(new[] { '͏', ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
                    if (split.Length == 2)
                    {
                        ourBlockedAvatars[split[0].Trim()] = split[1];
                    }
                }
            }

            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(VRCAvatarManager).GetMethod(
                                                                                                   nameof(VRCAvatarManager.Method_Public_Boolean_ApiAvatar_String_Single_MulticastDelegateNPublicSealedVoGaVRBoUnique_0)))
                                            .GetValue(null);

                Imports.Hook((IntPtr)(&originalMethodPointer), typeof(AvatarHiding).GetMethod(nameof(SwitchAvatarPatch), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer());

                ourSwitchAvatar = Marshal.GetDelegateForFunctionPointer <SwitchAvatarDelegate>(originalMethodPointer);
            }

            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(FeaturePermissionManager).GetMethods()
                                                                                               .Single(it =>
                                                                                                       it.Name.StartsWith("Method_Public_Boolean_APIUser_byref_EnumPublicSealedva5vUnique_") &&
                                                                                                       it.GetCustomAttribute <CallerCountAttribute>().Count > 0))
                                            .GetValue(null);

                Imports.Hook((IntPtr)(&originalMethodPointer), typeof(AvatarHiding).GetMethod(nameof(CanUseCustomAvatarPatch), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer());

                ourCanUseCustomAvatarDelegate = Marshal.GetDelegateForFunctionPointer <CanUseCustomAvatarDelegate>(originalMethodPointer);
            }
        }
Example #13
0
        public static unsafe IEnumerable <XrefInstance> XrefScan(MethodBase methodBase)
        {
            var fieldValue = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodBase)?.GetValue(null);

            if (fieldValue == null)
            {
                return(Enumerable.Empty <XrefInstance>());
            }

            XrefScanMetadataUtil.CallMetadataInitForMethod(methodBase);

            return(XrefScanImpl(DecoderForAddress(*(IntPtr *)(IntPtr)fieldValue)));
        }
Example #14
0
        public unsafe static void HookAll()
        {
            Log.Info("Creating detours for hammer attack checks...");

            var hammerAttackTargetCheckPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                                 .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(MeleeWeaponFirstPerson).GetMethod(nameof(MeleeWeaponFirstPerson.CheckForAttackTargets)))
                                                 .GetValue(null);

            FastNativeDetour.CreateAndApply(hammerAttackTargetCheckPointer,
                                            OurAttackCheck,
                                            out OriginalHammerMethod,
                                            CallingConvention.Cdecl);
        }
Example #15
0
 public static void OnApplicationStart()
 {
     unsafe
     {
         var originalMethod = *(IntPtr *)(IntPtr)UnhollowerUtils
                              .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(
             typeof(ObjectInstantiator).GetMethod(nameof(ObjectInstantiator._InstantiateObject)))
                              .GetValue(null);
         Imports.Hook((IntPtr)(&originalMethod),
                      typeof(PortalHiding).GetMethod(nameof(InstantiateObjectPatch),
                                                     BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer());
         ourDelegate = Marshal.GetDelegateForFunctionPointer <InstantiateObjectDelegate>(originalMethod);
     }
 }
Example #16
0
        public static void Patch()
        {
            unsafe
            {
                var setupMethod = typeof(PlayerManager).GetMethods()
                                  .Where(method => method.Name.StartsWith("Method_Public_Static_IEnumerable_1_Player_Vector3_Single_Nullable_1_Int32_Func_2_Player_Boolean_"))
                                  .OrderBy(UnhollowerSupport.GetIl2CppMethodCallerCount).Last();

                var originalMethod = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(setupMethod).GetValue(null);

                MelonUtils.NativeHookAttach((IntPtr)(&originalMethod), typeof(PlayerIEnumerableSetup).GetMethod(nameof(EnumerableSetup),
                                                                                                                BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer());

                _playerIEnumerableSetupDelegate = Marshal.GetDelegateForFunctionPointer <PlayerIEnumerableSetupDelegate>(originalMethod);
            }
        }
Example #17
0
        private static ISupportModule Initialize()
        {
            if (Console.Enabled || Imports.IsDebugMode())
            {
                LogSupport.InfoHandler -= System.Console.WriteLine;
                LogSupport.InfoHandler += MelonModLogger.Log;
            }
            LogSupport.WarningHandler -= System.Console.WriteLine;
            LogSupport.WarningHandler += MelonModLogger.LogWarning;
            LogSupport.ErrorHandler   -= System.Console.WriteLine;
            LogSupport.ErrorHandler   += MelonModLogger.LogError;
            if (Imports.IsDebugMode())
            {
                LogSupport.TraceHandler -= System.Console.WriteLine;
                LogSupport.TraceHandler += MelonModLogger.Log;
            }

            try
            {
                unsafe {
                    var tlsHookTarget    = typeof(Uri).Assembly.GetType("Mono.Unity.UnityTls").GetMethod("GetUnityTlsInterface", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).MethodHandle.GetFunctionPointer();
                    var unityMethodField = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(Il2CppMono.Unity.UnityTls).GetMethod("GetUnityTlsInterface", BindingFlags.Public | BindingFlags.Static));
                    var unityMethodPtr   = (IntPtr)unityMethodField.GetValue(null);
                    var unityMethod      = *(IntPtr *)unityMethodPtr;
                    Imports.Hook((IntPtr)(&tlsHookTarget), unityMethod);
                }
            } catch (Exception ex) {
                MelonModLogger.LogWarning("Exception while setting up TLS, mods will not be able to use HTTPS: " + ex);
            }

            ClassInjector.DoHook += Imports.Hook;
            GetUnityVersionNumbers(out var major, out var minor, out var patch);
            UnityVersionHandler.Initialize(major, minor, patch);
            ClassInjector.RegisterTypeInIl2Cpp <MelonLoaderComponent>();
            MelonLoaderComponent.CreateComponent();
            SceneManager.sceneLoaded = (
                (SceneManager.sceneLoaded == null)
                ? new Action <Scene, LoadSceneMode>(OnSceneLoad)
                : Il2CppSystem.Delegate.Combine(SceneManager.sceneLoaded, (UnityAction <Scene, LoadSceneMode>) new Action <Scene, LoadSceneMode>(OnSceneLoad)).Cast <UnityAction <Scene, LoadSceneMode> >()
                );
            Camera.onPostRender = (
                (Camera.onPostRender == null)
                ? new Action <Camera>(OnPostRender)
                : Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback) new Action <Camera>(OnPostRender)).Cast <Camera.CameraCallback>()
                );
            return(new Module());
        }
Example #18
0
        public unsafe static void HookAll()
        {
            Log.Info("Patching bioscanner functions...");

            var tryGetTaggableEnemiesPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                               .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(typeof(EnemyScanner).GetMethod(nameof(EnemyScanner.TryGetTaggableEnemies)))
                                               .GetValue(null);

            FastNativeDetour.CreateAndApply(tryGetTaggableEnemiesPointer,
                                            OurScannerMethod,
                                            out OriginalScannerMethod,
                                            CallingConvention.Cdecl);

            FastNativeDetour.CreateAndApply(
                IL2CPP.il2cpp_resolve_icall("UnityEngine.Transform::" + nameof(Transform.get_rotation_Injected)),
                OurGetRotation, out ourOriginalRotationGetter, CallingConvention.Cdecl);
        }
Example #19
0
        public static void Patch()
        {
            unsafe
            {
                var setupMethod = typeof(PageWorldInfo).GetMethods()
                                  .Where(m =>
                                         m.Name.StartsWith("Method_Public_Void_ApiWorld_ApiWorldInstance_Boolean_Boolean_") &&
                                         !m.Name.Contains("PDM"))
                                  .OrderBy(m => m.GetCustomAttribute <CallerCountAttribute>().Count)
                                  .Last();

                // Thanks to Knah
                var originalMethod = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(setupMethod).GetValue(null);

                MelonUtils.NativeHookAttach((IntPtr)(&originalMethod), typeof(WorldInfoSetup).GetMethod(nameof(Postfix), BindingFlags.Static | BindingFlags.Public) !.MethodHandle.GetFunctionPointer());

                worldInfoSetupDelegate = Marshal.GetDelegateForFunctionPointer <WorldInfoSetupDelegate>(originalMethod);
            }
        }
Example #20
0
        public static void DoPatch()
        {
            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(
                    typeof(ApiModel).GetMethods().Single(it =>
                                                         it.Name == nameof(ApiModel.SetApiFieldsFromJson) && it.GetParameters().Length == 2))
                                            .GetValue(null);
                Imports.Hook((IntPtr)(&originalMethodPointer), typeof(ApiSnifferPatch).GetMethod(nameof(ApiSnifferStatic)) !.MethodHandle.GetFunctionPointer());
                ourOriginalApiPopulate = Marshal.GetDelegateForFunctionPointer <ApiPopulateDelegate>(originalMethodPointer);
            }

            unsafe
            {
                var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(ImageDownloaderClosureType.GetMethod(nameof(ImageDownloaderClosure._DownloadImageInternal_b__0))).GetValue(null);
                Imports.Hook((IntPtr)(&originalMethodPointer), typeof(ApiSnifferPatch).GetMethod(nameof(ImageSnifferPatch)) !.MethodHandle.GetFunctionPointer());
                ourOriginalOnDone = Marshal.GetDelegateForFunctionPointer <ImageDownloaderOnDoneDelegate>(originalMethodPointer);
            }
        }
        internal static unsafe bool CallMetadataInitForMethod(MethodBase method)
        {
            if (ourMetadataInitForMethodPointer == IntPtr.Zero)
            {
                FindMetadataInitForMethod();
            }

            var nativeMethodInfoObject = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method)?.GetValue(null);

            if (nativeMethodInfoObject == null)
            {
                return(false);
            }
            var nativeMethodInfo = (IntPtr)nativeMethodInfoObject;
            var codeStart        = *(IntPtr *)nativeMethodInfo;
            var firstCall        = XrefScannerLowLevel.JumpTargets(codeStart).FirstOrDefault();

            if (firstCall != ourMetadataInitForMethodPointer || firstCall == IntPtr.Zero)
            {
                return(false);
            }

            var tokenPointer    = XrefScanUtilFinder.FindLastRcxReadAddressBeforeCallTo(codeStart, ourMetadataInitForMethodPointer);
            var initFlagPointer = XrefScanUtilFinder.FindByteWriteTargetRightAfterCallTo(codeStart, ourMetadataInitForMethodPointer);

            if (tokenPointer == IntPtr.Zero || initFlagPointer == IntPtr.Zero)
            {
                return(false);
            }

            if (Marshal.ReadByte(initFlagPointer) == 0)
            {
                ourMetadataInitForMethodDelegate(Marshal.ReadInt32(tokenPointer));
                Marshal.WriteByte(initFlagPointer, 1);
            }

            return(true);
        }
Example #22
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();

            MethodBase patchTarget = null;

            foreach (var methodInfo in typeof(AssetManagement).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly))
            {
                foreach (var it in XrefScanner.XrefScan(methodInfo))
                {
                    if (it.Type != XrefType.Method)
                    {
                        continue;
                    }
                    var methodBase = it.TryResolve();
                    if (methodBase == null)
                    {
                        continue;
                    }
                    if (matchingMethods.Contains(methodBase))
                    {
                        patchTarget = methodBase;
                        goto haveTarget;
                    }
                }
            }

haveTarget:
            if (patchTarget != null)
            {
                unsafe
                {
                    var originalMethodPointer = *(IntPtr *)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(patchTarget).GetValue(null);

                    Imports.Hook((IntPtr)(&originalMethodPointer),
                                 typeof(AdvancedSafetyMod).GetMethod(nameof(ObjectInstantiatePatch),
                                                                     BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle.GetFunctionPointer());

                    ourOriginalInstantiate =
                        Marshal.GetDelegateForFunctionPointer <ObjectInstantiateDelegate>(originalMethodPointer);
                }
            }
            else
            {
                MelonLogger.LogError("Patch target for object instantiation not found, avatar filtering will not work");
            }

            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 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();

            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]);
            }
        }
Example #23
0
        public override void OnApplicationStart()
        {
            advInvPreferencesCategory = MelonPreferences.CreateCategory("AdvancedInvites", "Advanced Invites");

            advInvPreferencesCategory.CreateEntry("DeleteNotifications", InviteHandler.DeleteNotifications, "Delete Notification After Successful Use");
            advInvPreferencesCategory.CreateEntry("BlacklistEnabled", blacklistEnabled, "Blacklist System");
            advInvPreferencesCategory.CreateEntry("WhitelistEnabled", whitelistEnabled, "Whitelist System");
            advInvPreferencesCategory.CreateEntry("NotificationVolume", .8f, "Notification Volume");
            advInvPreferencesCategory.CreateEntry("JoinMeNotifyRequest", joinMeNotifyRequest, "Join Me Req Notification Sound");
            advInvPreferencesCategory.CreateEntry("IgnoreBusyStatus", ignoreBusyStatus, "Ignore Busy Status");

            advInvPreferencesCategory.CreateEntry("InviteSoundEnabled", true, "Invite Sound");
            advInvPreferencesCategory.CreateEntry("InviteRequestSoundEnabled", true, "Invite-Request Sound");
            advInvPreferencesCategory.CreateEntry("VoteToKickSoundEnabled", false, "Vote-Kick Sound", true);
            advInvPreferencesCategory.CreateEntry("FriendRequestSoundEnabled", false, "Friend-Request Sound", true);
            OnPreferencesLoaded();

            Localization.Load();

        #if DEBUG
            DebugTesting.Test();

            try
            {
                MethodInfo sendNotificationMethod = typeof(NotificationManager).GetMethod(
                    nameof(NotificationManager.Method_Public_Void_String_String_String_String_NotificationDetails_ArrayOf_Byte_0),
                    BindingFlags.Public | BindingFlags.Instance);
                Harmony.Patch(sendNotificationMethod, new HarmonyMethod(
                                  typeof(AdvancedInviteSystem).GetMethod(nameof(SendNotificationPatch), BindingFlags.NonPublic | BindingFlags.Static)));
            }
            catch (Exception e)
            {
                MelonLogger.Error("Error Patching SendNotification: " + e.Message);
            }
        #endif

            try
            {
                unsafe
                {
                    // Appears to be NotificationManager.Method_Private_Void_Notification_1
                    MethodInfo acceptNotificationMethod = typeof(NotificationManager).GetMethods(BindingFlags.Public | BindingFlags.Instance).Single(
                        m => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(Notification) &&
                        m.XRefScanFor("AcceptNotification for notification:"));
                    IntPtr originalMethod = *(IntPtr *)(IntPtr)UnhollowerUtils
                                            .GetIl2CppMethodInfoPointerFieldForGeneratedMethod(acceptNotificationMethod).GetValue(null);

                    MelonUtils.NativeHookAttach(
                        (IntPtr)(&originalMethod),
                        typeof(AdvancedInviteSystem).GetMethod(nameof(AcceptNotificationPatch), BindingFlags.Static | BindingFlags.NonPublic) !.MethodHandle
                        .GetFunctionPointer());
                    acceptNotificationDelegate = Marshal.GetDelegateForFunctionPointer <AcceptNotificationDelegate>(originalMethod);
                }
            }
            catch (Exception e)
            {
                MelonLogger.Error("Error Patching AcceptNotification: " + e.Message);
            }

            try
            {
                //Appears to be NotificationManager.Method_Private_String_Notification_1
                MethodInfo addNotificationMethod = typeof(NotificationManager).GetMethods(BindingFlags.Public | BindingFlags.Instance).Single(
                    m => m.Name.StartsWith("Method_Private_") && m.ReturnType == typeof(string) && m.GetParameters().Length == 1 &&
                    m.GetParameters()[0].ParameterType == typeof(Notification) && m.XRefScanFor("imageUrl"));
                Harmony.Patch(
                    addNotificationMethod,
                    postfix: new HarmonyMethod(
                        typeof(AdvancedInviteSystem).GetMethod(nameof(AddNotificationPatch), BindingFlags.NonPublic | BindingFlags.Static)));
            }
            catch (Exception e)
            {
                MelonLogger.Error("Error Patching AddNotification: " + e.Message);
            }

            UserPermissionHandler.LoadSettings();
            WorldPermissionHandler.LoadSettings();
            MelonCoroutines.Start(WaitForVrChatUiManager());
        }
 public FieldInfo MethodBaseToIl2CppFieldInfo(MethodBase method)
 => UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method);
Example #25
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]);
            }
        }
Example #26
0
        private static ISupportModule Initialize()
        {
            LogSupport.RemoveAllHandlers();
            if (Console.Enabled || Imports.IsDebugMode())
            {
                LogSupport.InfoHandler += MelonModLogger.Log;
            }
            LogSupport.WarningHandler += MelonModLogger.LogWarning;
            LogSupport.ErrorHandler   += MelonModLogger.LogError;
            if (Imports.IsDebugMode())
            {
                LogSupport.TraceHandler += MelonModLogger.Log;
            }

            try
            {
                Assembly il2cppSystem = Assembly.Load("Il2CppSystem");
                if (il2cppSystem != null)
                {
                    Type unitytls = il2cppSystem.GetType("Il2CppMono.Unity.UnityTls");
                    if (unitytls != null)
                    {
                        unsafe
                        {
                            var tlsHookTarget    = typeof(Uri).Assembly.GetType("Mono.Unity.UnityTls").GetMethod("GetUnityTlsInterface", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).MethodHandle.GetFunctionPointer();
                            var unityMethodField = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(unitytls.GetMethod("GetUnityTlsInterface", BindingFlags.Public | BindingFlags.Static));
                            var unityMethodPtr   = (IntPtr)unityMethodField.GetValue(null);
                            var unityMethod      = *(IntPtr *)unityMethodPtr;
                            Imports.Hook((IntPtr)(&tlsHookTarget), unityMethod);
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to get Type Il2CppMono.Unity.UnityTls!");
                    }
                }
                else
                {
                    throw new Exception("Failed to get Assembly Il2CppSystem!");
                }
            }
            catch (Exception ex)
            {
                MelonModLogger.LogWarning("Exception while setting up TLS, mods will not be able to use HTTPS: " + ex);
            }

            if (MelonLoader.Main.IsVRChat)
            {
                try
                {
                    Assembly Transmtn = Assembly.Load("Transmtn");
                    if (Transmtn != null)
                    {
                        Type Transmtn_HttpConnection = Transmtn.GetType("Transmtn.HttpConnection");
                        if (Transmtn_HttpConnection != null)
                        {
                            Il2CppSystem_Console_WriteLine = typeof(Il2CppSystem.Console).GetMethods(BindingFlags.Public | BindingFlags.Static).First(x => (x.Name.Equals("WriteLine") && (x.GetParameters().Count() == 1) && (x.GetParameters()[0].ParameterType == typeof(string))));
                            if (harmonyInstance == null)
                            {
                                harmonyInstance = HarmonyInstance.Create("MelonLoader.Support.Il2Cpp");
                            }
                            harmonyInstance.Patch(Transmtn_HttpConnection.GetMethod("get", BindingFlags.Public | BindingFlags.Instance), new HarmonyMethod(typeof(Main).GetMethod("Transmtn_HttpConnection_get_Prefix", BindingFlags.NonPublic | BindingFlags.Static)), new HarmonyMethod(typeof(Main).GetMethod("Transmtn_HttpConnection_get_Postfix", BindingFlags.NonPublic | BindingFlags.Static)));
                        }
                        else
                        {
                            throw new Exception("Failed to get Type Transmtn.HttpConnection!");
                        }
                    }
                    else
                    {
                        throw new Exception("Failed to get Assembly Transmtn!");
                    }
                }
                catch (Exception ex)
                {
                    MelonModLogger.LogWarning("Exception while setting up Auth Token Hider, Auth Tokens may show in Console: " + ex);
                }
            }

            ClassInjector.DoHook += Imports.Hook;
            GetUnityVersionNumbers(out var major, out var minor, out var patch);
            UnityVersionHandler.Initialize(major, minor, patch);

            SetAsLastSiblingDelegateField = IL2CPP.ResolveICall <SetAsLastSiblingDelegate>("UnityEngine.Transform::SetAsLastSibling");

            ClassInjector.RegisterTypeInIl2Cpp <MelonLoaderComponent>();
            MelonLoaderComponent.Create();

            SceneManager.sceneLoaded = (
                (SceneManager.sceneLoaded == null)
                ? new Action <Scene, LoadSceneMode>(OnSceneLoad)
                : Il2CppSystem.Delegate.Combine(SceneManager.sceneLoaded, (UnityAction <Scene, LoadSceneMode>) new Action <Scene, LoadSceneMode>(OnSceneLoad)).Cast <UnityAction <Scene, LoadSceneMode> >()
                );
            Camera.onPostRender = (
                (Camera.onPostRender == null)
                ? new Action <Camera>(OnPostRender)
                : Il2CppSystem.Delegate.Combine(Camera.onPostRender, (Camera.CameraCallback) new Action <Camera>(OnPostRender)).Cast <Camera.CameraCallback>()
                );

            return(new Module());
        }
Example #27
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);

                    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]);
            }
        }
Example #28
0
        public override void OnApplicationStart()
        {
            ClassInjector.RegisterTypeInIl2Cpp <BoneDeleteHandler>();

            var category = MelonPreferences.CreateCategory("Turbones");
            var enableCollisionChecks = category.CreateEntry("OptimizedCollisionChecks", true, "Enable optimized collision checks");
            var enableUpdate          = category.CreateEntry("OptimizedUpdate", true, "Enable optimized simulation");
            var updateMultiThread     = category.CreateEntry("OptimizedMultiThread", false, "Enable multithreading (placebo!)");
            var threadCount           = category.CreateEntry("DynamicBoneThreads", Math.Max(1, Environment.ProcessorCount / 2 - 1), "Thread count (placebo!)", dont_save_default: true);

            var dllName = "JigglyRustSolver.dll";

            try
            {
                using var resourceStream = Assembly.GetExecutingAssembly()
                                           .GetManifestResourceStream(typeof(TurbonesMod), dllName);
                using var fileStream = File.Open("VRChat_Data/Plugins/" + dllName, FileMode.Create, FileAccess.Write);

                resourceStream.CopyTo(fileStream);
            }
            catch (IOException ex)
            {
                MelonLogger.Warning("Failed to write native dll; will attempt loading it anyway. This is normal if you're running multiple instances of VRChat");
                MelonDebug.Msg(ex.ToString());
            }

            if (!JigglySolverApi.Initialize("VRChat_Data/Plugins/" + dllName))
            {
                MelonLogger.Error("Error initializing native library; mod won't work");
                return;
            }

            ourDynBoneCollideEntryPoint = Marshal.ReadIntPtr((IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(
                                                                 typeof(DynamicBoneCollider).GetMethod(nameof(DynamicBoneCollider
                                                                                                              .Method_Public_Void_byref_Vector3_Single_0))).GetValue(null));

            ourDynBoneUpdateEntryPoint = Marshal.ReadIntPtr((IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(
                                                                typeof(DynamicBone).GetMethod(nameof(DynamicBone
                                                                                                     .Method_Private_Void_Single_Boolean_0))).GetValue(null));

            var isCollidePatched = false;


            unsafe void PatchCollide()
            {
                if (isCollidePatched)
                {
                    return;

                    fixed(IntPtr *a = &ourDynBoneCollideEntryPoint)
                    MelonUtils.NativeHookAttach((IntPtr)a, JigglySolverApi.LibDynBoneCollideEntryPoint);

                    MelonLogger.Msg("Patched DynamicBone Collide");
                    isCollidePatched = true;
            }

            unsafe void UnpatchCollide()
            {
                if (!isCollidePatched)
                {
                    return;

                    fixed(IntPtr *a = &ourDynBoneCollideEntryPoint)
                    MelonUtils.NativeHookDetach((IntPtr)a, JigglySolverApi.LibDynBoneCollideEntryPoint);

                    MelonLogger.Msg("Unpatched DynamicBone Collide");
                    isCollidePatched = false;
            }

            unsafe void RepatchUpdate(bool useFast, bool useMt)
            {
                // TODO: re-enable multithreading if it ever gets useful/stable
                useMt = false;

                if (ourLastPatchPointer != IntPtr.Zero)
                {
                    fixed(IntPtr *a = &ourDynBoneUpdateEntryPoint)
                    MelonUtils.NativeHookDetach((IntPtr)a, ourLastPatchPointer);

                    MelonLogger.Msg("Unpatched DynamicBone Update");
                    ourLastPatchPointer = IntPtr.Zero;
                }

                if (!CheckWasSuccessful)
                    return; }

                if (useFast)
                {
                    ourLastPatchPointer = useMt ? JigglySolverApi.LibDynBoneUpdateMultiThreaded : JigglySolverApi.LibDynBoneUpdateSingleThreaded;

                    fixed(IntPtr *a = &ourDynBoneUpdateEntryPoint)
                    MelonUtils.NativeHookAttach((IntPtr)a, ourLastPatchPointer);

                    MelonLogger.Msg($"Patched DynamicBone Update (multithreaded: {useMt})");
                }
                else
                {
                    ourLastPatchPointer = JigglySolverApi.DynamicBoneUpdateNotifyPatch;

                    fixed(IntPtr *a = &ourDynBoneUpdateEntryPoint)
                    MelonUtils.NativeHookAttach((IntPtr)a, ourLastPatchPointer);

                    JigglySolverApi.SetOriginalBoneUpdateDelegate(ourDynBoneUpdateEntryPoint);

                    MelonLogger.Msg($"Patched DynamicBone Update (notify)");
                }
            }

            CheckDummyThree();

            enableCollisionChecks.OnValueChanged += (_, v) =>
            {
                if (v)
                    PatchCollide(); }
Example #29
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]);
            }
        }