Exemplo n.º 1
0
        private static ISupportModule Initialize()
        {
            LogSupport.RemoveAllHandlers();
            if (CumConsole.Enabled || Imports.IsDebugMode())
            {
                LogSupport.InfoHandler += CumLogger.Log;
            }
            LogSupport.WarningHandler += CumLogger.LogWarning;
            LogSupport.ErrorHandler   += CumLogger.LogError;
            if (Imports.IsDebugMode())
            {
                LogSupport.TraceHandler += CumLogger.Log;
            }

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

            // Il2CppSystem.Console.SetOut(new Il2CppSystem.IO.StreamWriter(Il2CppSystem.IO.Stream.Null));
            try
            {
                var il2CppSystemAssembly = Assembly.Load("Il2Cppmscorlib");

                var consoleType      = il2CppSystemAssembly.GetType("Il2CppSystem.Console");
                var streamWriterType = il2CppSystemAssembly.GetType("Il2CppSystem.IO.StreamWriter");
                var streamType       = il2CppSystemAssembly.GetType("Il2CppSystem.IO.Stream");

                var setOutMethod     = consoleType.GetMethod("SetOut", BindingFlags.Static | BindingFlags.Public);
                var nullStreamField  = streamType.GetProperty("Null", BindingFlags.Static | BindingFlags.Public).GetGetMethod();
                var streamWriterCtor = streamWriterType.GetConstructor(new[] { streamType });

                var nullStream  = nullStreamField.Invoke(null, new object[0]);
                var steamWriter = streamWriterCtor.Invoke(new[] { nullStream });
                setOutMethod.Invoke(null, new[] { steamWriter });
            }
            catch (Exception ex)
            {
                CumLogger.LogError($"Console cleaning failed: {ex}");
            }

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

            ClassInjector.RegisterTypeInIl2Cpp <CumLoaderComponent>();
            CumLoaderComponent.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());
        }
Exemplo n.º 2
0
        private static IEnumerable <CodeInstruction> UnhollowerTranspiler(MethodBase method, IEnumerable <CodeInstruction> instructionsIn)
        {
            List <CodeInstruction> instructions = new List <CodeInstruction>(instructionsIn);
            PatchInfo patchInfo        = HarmonySharedState.GetPatchInfo(method);
            IntPtr    copiedMethodInfo = patchInfo.copiedMethodInfoPointer;

            bool found        = false;
            int  replaceIdx   = 0;
            int  replaceCount = 0;

            for (int i = instructions.Count - 2; i >= 0; --i)
            {
                if (instructions[i].opcode != OpCodes.Ldsfld)
                {
                    continue;
                }

                found = true;
                CodeInstruction next = instructions[i + 1];
                if (next.opcode == OpCodes.Call && ((MethodInfo)next.operand).Name == "il2cpp_object_get_virtual_method")
                {
                    // Virtual method: Replace the sequence
                    // - ldarg.0
                    // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::Il2CppObjectBaseToPtr(class [UnhollowerBaseLib] UnhollowerBaseLib.Il2CppObjectBase)
                    // - ldsfld native int SomeClass::NativeMethodInfoPtr_Etc
                    // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::il2cpp_object_get_virtual_method(native int, native int)

                    replaceIdx   = i - 2;
                    replaceCount = 4;
                }
                else
                {
                    // Everything else: Just replace the static load
                    replaceIdx   = i;
                    replaceCount = 1;
                }
                break;
            }

            if (!found)
            {
                CumLogger.LogError("Harmony transpiler could not rewrite Unhollower method. Expect a stack overflow.");
                return(instructions);
            }

            CodeInstruction[] replacement =
            {
                new CodeInstruction(OpCodes.Ldc_I8, copiedMethodInfo.ToInt64()),
                new CodeInstruction(OpCodes.Conv_I)
            };

            instructions.RemoveRange(replaceIdx, replaceCount);
            instructions.InsertRange(replaceIdx, replacement);

            return(instructions);
        }
Exemplo n.º 3
0
 public override void OnModSettingsApplied() // Runs when Mod Preferences get saved to CumData/modprefs.ini.
 {
     CumLogger.Log("OnModSettingsApplied");
 }
Exemplo n.º 4
0
 public override void OnApplicationQuit() // Runs when the Game is told to Close.
 {
     CumLogger.Log("OnApplicationQuit");
 }
Exemplo n.º 5
0
 public override void OnApplicationStart() // Runs after Game Initialization.
 {
     CumLogger.Log("OnApplicationStart");
 }
Exemplo n.º 6
0
 public override void OnPreInitialization() // Runs before Game Initialization.
 {
     CumLogger.Log("OnPreInitialization");
 }
Exemplo n.º 7
0
 public override void VRChat_OnUiManagerInit() // Runs upon VRChat's UiManager Initialization. Only runs if the Mod is used in VRChat.
 {
     CumLogger.Log("VRChat_OnUiManagerInit");
 }
Exemplo n.º 8
0
 public override void OnGUI() // Can run multiple times per frame. Mostly used for Unity's IMGUI.
 {
     CumLogger.Log("OnGUI");
 }
Exemplo n.º 9
0
 public override void OnLateUpdate() // Runs once per frame after OnUpdate and OnFixedUpdate have finished.
 {
     CumLogger.Log("OnLateUpdate");
 }
Exemplo n.º 10
0
 public override void OnFixedUpdate() // Can run multiple times per frame. Mostly used for Physics.
 {
     CumLogger.Log("OnFixedUpdate");
 }
Exemplo n.º 11
0
 public override void OnUpdate() // Runs once per frame.
 {
     CumLogger.Log("OnUpdate");
 }
Exemplo n.º 12
0
 public override void OnLevelWasInitialized(int level) // Runs when a Scene has Initialized.
 {
     CumLogger.Log("OnLevelWasInitialized: " + level.ToString());
 }
Exemplo n.º 13
0
 public override void OnLevelIsLoading() // Runs when a Scene is Loading or when a Loading Screen is Shown. Currently only runs if the Mod is used in BONEWORKS.
 {
     CumLogger.Log("OnLevelIsLoading");
 }
Exemplo n.º 14
0
        private static void ProcessNextOfCoroutine(IEnumerator enumerator)
        {
            try
            {
                if (!enumerator.MoveNext()) // Run the next step of the coroutine. If it's done, restore the parent routine
                {
                    var indices = ourCoroutinesStore.Select((it, idx) => (idx, it)).Where(it => it.it.WaitCondition == enumerator).Select(it => it.idx).ToList();
                    for (var i = indices.Count - 1; i >= 0; i--)
                    {
                        var index = indices[i];
                        ourNextFrameCoroutines.Add(ourCoroutinesStore[index].Coroutine);
                        ourCoroutinesStore.RemoveAt(index);
                    }
                    return;
                }
            }
            catch (Exception e)
            {
                CumLogger.LogError(e.ToString());
                Stop(FindOriginalCoro(enumerator)); // We want the entire coroutine hierachy to stop when an error happen
            }

            var next = enumerator.Current;

            switch (next)
            {
            case null:
                ourNextFrameCoroutines.Add(enumerator);
                return;

            case WaitForFixedUpdate _:
                ourWaitForFixedUpdateCoroutines.Add(enumerator);
                return;

            case WaitForEndOfFrame _:
                ourWaitForEndOfFrameCoroutines.Add(enumerator);
                return;

            case WaitForSeconds _:
                break;     // do nothing, this one is supported in Process

            case Il2CppObjectBase il2CppObjectBase:
                var nextAsEnumerator = il2CppObjectBase.TryCast <Il2CppSystem.Collections.IEnumerator>();
                if (nextAsEnumerator != null)     // il2cpp IEnumerator also handles CustomYieldInstruction
                {
                    next = new Il2CppEnumeratorWrapper(nextAsEnumerator);
                }
                else
                {
                    CumLogger.LogWarning($"Unknown coroutine yield object of type {il2CppObjectBase} for coroutine {enumerator}");
                }
                break;
            }

            ourCoroutinesStore.Add(new CoroTuple {
                WaitCondition = next, Coroutine = enumerator
            });

            if (next is IEnumerator nextCoro)
            {
                ProcessNextOfCoroutine(nextCoro);
            }
        }