示例#1
0
        static void setEnabled(Type patchType, HarmonyPatch patch, bool enabled)
        {
            $"OptionalPatches: setEnabled {patchType} => {enabled}".logDbg();
            var method = patch.info.getTargetMethod();

            if (method == null)
            {
                "OptionalPatches: method is null!".logError();
                return;
            }

            var prefix     = patchType.method("Prefix");
            var postfix    = patchType.method("Postfix");
            var transpiler = patchType.method("Transpiler");

            var patches = HarmonyHelper.getPatchInfo(method);

            bool prefixActive     = patches.isPatchedBy(prefix);
            bool postfixActive    = patches.isPatchedBy(postfix);
            bool transpilerActive = patches.isPatchedBy(transpiler);

            if (enabled)
            {
                if (!prefixActive && !postfixActive && !transpilerActive)
                {
                    HarmonyHelper.patch(method, prefix, postfix, transpiler);
                }
            }
            else
            {
                // need to check if this is actual patches to avoid unnecessary updates in harmony (with transpilers especially)
                if (prefixActive)
                {
                    HarmonyHelper.unpatch(method, prefix);
                }
                if (postfixActive)
                {
                    HarmonyHelper.unpatch(method, postfix);
                }
                if (transpilerActive)
                {
                    HarmonyHelper.unpatch(method, transpiler);
                }
            }
        }
示例#2
0
        public void initDetours()
        {
            // TODO realize detouring with annotations
            if (!DetourInited)
            {
                Log.Info("Init detours");
                bool detourFailed = false;

                try {
                    Log.Info("Deploying Harmony patches");
#if DEBUG
                    HarmonyInstance.DEBUG = true;
#endif
                    Assembly assembly = Assembly.GetExecutingAssembly();

                    HarmonyMethodStates.Clear();

                    // Harmony attribute-driven patching
                    Log.Info($"Performing Harmony attribute-driven patching");
                    HarmonyInst = HarmonyInstance.Create(HARMONY_ID);
                    HarmonyInst.PatchAll(assembly);

                    foreach (Type type in assembly.GetTypes())
                    {
                        object[] attributes = type.GetCustomAttributes(typeof(HarmonyPatch), true);
                        if (attributes.Length <= 0)
                        {
                            continue;
                        }

                        foreach (object attr in attributes)
                        {
                            HarmonyPatch       harmonyPatchAttr = (HarmonyPatch)attr;
                            MethodBase         info             = HarmonyUtil.GetOriginalMethod(harmonyPatchAttr.info);
                            IntPtr             ptr   = info.MethodHandle.GetFunctionPointer();
                            RedirectCallsState state = RedirectionHelper.GetState(ptr);
                            HarmonyMethodStates[info] = state;
                        }
                    }

                    // Harmony manual patching
                    Log.Info($"Performing Harmony manual patching");
                    foreach (ManualHarmonyPatch manualPatch in ManualHarmonyPatches)
                    {
                        Log.Info($"Manually patching method {manualPatch.method.DeclaringType.FullName}.{manualPatch.method.Name}. Prefix: {manualPatch.prefix?.method}, Postfix: {manualPatch.postfix?.method}, Transpiler: {manualPatch.transpiler?.method}");
                        HarmonyInst.Patch(manualPatch.method, manualPatch.prefix, manualPatch.postfix, manualPatch.transpiler);

                        IntPtr             ptr   = manualPatch.method.MethodHandle.GetFunctionPointer();
                        RedirectCallsState state = RedirectionHelper.GetState(ptr);
                        HarmonyMethodStates[manualPatch.method] = state;
                    }
                } catch (Exception e) {
                    Log.Error("Could not deploy Harmony patches");
                    Log.Info(e.ToString());
                    Log.Info(e.StackTrace);
                    detourFailed = true;
                }

                try {
                    Log.Info("Deploying attribute-driven detours");
                    DetouredMethodStates = AssemblyRedirector.Deploy();
                } catch (Exception e) {
                    Log.Error("Could not deploy attribute-driven detours");
                    Log.Info(e.ToString());
                    Log.Info(e.StackTrace);
                    detourFailed = true;
                }

                if (detourFailed)
                {
                    Log.Info("Detours failed");
                    Singleton <SimulationManager> .instance.m_ThreadingWrapper.QueueMainThread(() => {
                        UIView.library.ShowModal <ExceptionPanel>("ExceptionPanel").SetMessage("TM:PE failed to load", "Traffic Manager: President Edition failed to load. You can continue playing but it's NOT recommended. Traffic Manager will not work as expected.", true);
                    });
                }
                else
                {
                    Log.Info("Detours successful");
                }

                DetourInited = true;
            }
        }
示例#3
0
        public bool CanApplyPatches()
        {
            var conflict = new List <string>(new string[] {
                "Actor_cp",
                "Actor_hp",
                "Actor_Vp",
                "ActorDeadDropModule_Handler",
                "ItemBag_ChangeMoney",
                "Player_AddExp"
            });

            foreach (var ass in UnityModManager.modEntries)
            {
                if (ass.Info.DisplayName == "Portia Helper")
                {
                    continue;
                }

                string origin = ass.Info.DisplayName;

                foreach (var tp in ass.Assembly.GetTypes())
                {
                    if (!Attribute.IsDefined(tp, typeof(HarmonyPatch)))
                    {
                        continue;
                    }

                    object[] attrs      = tp.GetCustomAttributes(true);
                    string   methodName = "";
                    string   typeName   = "";

                    foreach (var attr in attrs)
                    {
                        HarmonyPatch hpAttr = attr as HarmonyPatch;

                        if (hpAttr is null)
                        {
                            continue;
                        }

                        if (methodName == "" && hpAttr.info.methodName != "")
                        {
                            methodName = hpAttr.info.methodName;
                        }

                        if (typeName == "" && hpAttr.info.declaringType.Name != "")
                        {
                            typeName = hpAttr.info.declaringType.Name;
                        }

                        if (methodName != "" && typeName != "")
                        {
                            break;
                        }
                    }

                    if (methodName != "" && typeName != "")
                    {
                        string key = $"{typeName}_{methodName}";

                        if (conflict.IndexOf(key) < 0)
                        {
                            continue;
                        }

                        if (_takenPatches.ContainsKey(key))
                        {
                            continue;
                        }

                        _takenPatches.Add(key, origin);
                    }
                }
            }

            return(_takenPatches.Count == 0);
        }