// =====================================================================
        // Shared Utility Functions
        // =====================================================================

        private static bool HigherTaxesModExists(HarmonyInstance harmonyInstance)
        {
            try
            {
                // Check if HigherTaxes exists by looking for specific patches.
                var Player_IncreaseTaxRate   = typeof(Player).GetMethod("IncreaseTaxRate");
                var Home_GetHappinessFromTax = typeof(Home).GetMethod("GetHappinessFromTax",
                                                                      BindingFlags.NonPublic | BindingFlags.Instance);

                bool Player_IncreaseTaxRate_patched   = false;
                bool Home_GetHappinessFromTax_patched = false;

                // Check for patch that removes the 30% limit.
                var info = harmonyInstance.GetPatchInfo(Player_IncreaseTaxRate);
                if (info == null)
                {
                    return(false);
                }
                foreach (var patch in info.Prefixes)
                {
                    if (patch.owner == "cmjten10.HigherTaxes")
                    {
                        Player_IncreaseTaxRate_patched = true;
                        break;
                    }
                }
                if (!Player_IncreaseTaxRate_patched)
                {
                    return(false);
                }

                // Check for patch that decreases happiness further past 30%.
                info = harmonyInstance.GetPatchInfo(Home_GetHappinessFromTax);
                if (info == null)
                {
                    return(false);
                }
                foreach (var patch in info.Postfixes)
                {
                    if (patch.owner == "cmjten10.HigherTaxes")
                    {
                        Home_GetHappinessFromTax_patched = true;
                        break;
                    }
                }
                return(Home_GetHappinessFromTax_patched);
            }
            catch
            {
                return(false);
            }
        }
示例#2
0
        private IEnumerable <Patch> GetSortedPatches(HarmonyInstance harmonyInstance, MethodBase method)
        {
            Patches patches = harmonyInstance.GetPatchInfo(method);

            return(patches.Prefixes.OrderByDescending(patch => patch.priority)
                   .Concat(patches.Transpilers.OrderByDescending(patch => patch.priority))
                   .Concat(patches.Postfixes.OrderByDescending(patch => patch.priority)));
        }
 /// <summary>
 /// Extension method to HarmonyInstance, used to record the state of patching when invoked
 /// </summary>
 /// <param name="harmonyInstance">An instance of HarmonyInstance</param>
 /// <param name="method">The method to audit</param>
 public static void AuditPatches(this HarmonyInstance harmonyInstance, MethodBase method)
 {
     if (!MethodPatches.TryGetValue(method, out var patchlist))
     {
         patchlist = new List <PatchDatum>();
     }
     patchlist.Add(new PatchDatum(harmonyInstance.GetPatchInfo(method)));
     MethodPatches[method] = patchlist;
 }
示例#4
0
    static void PostfixOnce(this HarmonyInstance instance, MethodInfo original, MethodInfo postfix)
    {
        var postfixes = instance.GetPatchInfo(original)?.Postfixes;

        if (postfixes == null || !postfixes.Any(patch => patch != null && patch.owner == _multiversionmodfix))
        {
            instance.Patch(original, postfix: new HarmonyMethod(postfix));
        }
    }
        private static void ConditionalPatch(HarmonyInstance harmony, MethodBase method, HarmonyMethod prefix, HarmonyMethod postfix)
        {
            if (harmony.GetPatchInfo(method)?.Owners?.Contains(harmony.Id) == true)
            {
#if DEBUG
                Debug.LogWarningFormat("TransferInfo: HarmonyPatches.ConditionalPatch - Harmony patches already present for {0}", string.Format("{0}.{1}", method.ReflectedType?.Name ?? "(null)", method.Name));
#endif
                return;
            }
            harmony.Patch(method, prefix, postfix);
        }
        public void Disable(UnityModManager.ModEntry modEntry, bool unpatch = false)
        {
            _logger = modEntry.Logger;

            using (ProcessLogger process = new ProcessLogger(_logger))
            {
                process.Log("Disabling.");

                Enabled = false;

                // use try-catch to prevent the progression being disrupt by exceptions
                if (_eventHandlers != null)
                {
                    process.Log("Raising events: OnDisable()");
                    for (int i = _eventHandlers.Count - 1; i >= 0; i--)
                    {
                        try { _eventHandlers[i].HandleModDisable(); }
                        catch (Exception e) { Error(e); }
                    }
                    _eventHandlers = null;
                }

                if (unpatch)
                {
                    HarmonyInstance harmonyInstance = HarmonyInstance.Create(modEntry.Info.Id);
                    foreach (MethodBase method in harmonyInstance.GetPatchedMethods().ToList())
                    {
                        Patches             patchInfo = harmonyInstance.GetPatchInfo(method);
                        IEnumerable <Patch> patches   =
                            patchInfo.Transpilers.Concat(patchInfo.Postfixes).Concat(patchInfo.Prefixes)
                            .Where(patch => patch.owner == modEntry.Info.Id);
                        if (patches.Any())
                        {
                            process.Log($"Unpatching: {patches.First().patch.DeclaringType.DeclaringType?.Name}.{method.DeclaringType.Name}.{method.Name}");
                            foreach (Patch patch in patches)
                            {
                                try { harmonyInstance.Unpatch(method, patch.patch); }
                                catch (Exception e) { Error(e); }
                            }
                        }
                    }
                    Patched = false;
                }

                modEntry.OnSaveGUI -= HandleSaveGUI;
                Core     = null;
                Settings = null;
                Version  = null;
                _logger  = null;

                process.Log("Disabled.");
            }
        }
示例#7
0
        private static void ConditionalPatch(this HarmonyInstance harmony, MethodBase method, HarmonyMethod prefix, HarmonyMethod postfix)
        {
            var fullMethodName = string.Format("{0}.{1}", method.ReflectedType?.Name ?? "(null)", method.Name);

            if (harmony.GetPatchInfo(method)?.Owners?.Contains(harmony.Id) == true)
            {
                Debug.LogWarningFormat("Harmony patches already present for {0}", fullMethodName);
            }
            else
            {
                Debug.LogFormat("Patching {0}...", fullMethodName);
                harmony.Patch(method, prefix, postfix);
            }
        }
示例#8
0
        static void FixPatches(HarmonyInstance harmony)
        {
            var original = typeof(CharacterBuildController).GetMethod("OnShow", BindingFlags.Instance | BindingFlags.NonPublic);

            if (original == null)
            {
                Log("Can't find method CharacterBuildController.OnShow");
                return;
            }
            var info = harmony.GetPatchInfo(original);

            if (info == null)
            {
                Log("CharacterBuildController.OnShow is not patched!!!!");
                return;
            }
            harmony.Unpatch(original, HarmonyPatchType.Prefix, "Respec");
        }
示例#9
0
        private void RefreshListOfPatchOwners(string modId, bool reset = true)
        {
            if (reset || _modIdsToColor == null)
            {
                _modIdsToColor = new Dictionary <string, string>();
            }

            HarmonyInstance harmonyInstance = HarmonyInstance.Create(modId);

            foreach (Patch patch in harmonyInstance.GetPatchedMethods().SelectMany(method =>
            {
                Patches patches = harmonyInstance.GetPatchInfo(method);
                return(patches.Prefixes.Concat(patches.Transpilers).Concat(patches.Postfixes));
            }))
            {
                if (!_modIdsToColor.ContainsKey(patch.owner))
                {
                    _modIdsToColor[patch.owner] = ColorUtility.ToHtmlStringRGBA(UnityEngine.Random.ColorHSV(0f, 1f, 0.25f, 1f, 0.75f, 1f));
                }
            }
        }
示例#10
0
        private static void Unpatch(HarmonyInstance harmony, MethodBase b, string id, bool pre = true, bool post = true, bool trans = true, string onlyUnpatch = null)
        {
            //FileLog.Log($"checking to unpatch: {b.FullName()}");
            Patches pa = harmony.GetPatchInfo(b);

            if (pa == null)
            {
                //FileLog.Log("no patch attached");
                return;
            }
            if (pre)
            {
                UnpatchCheckList(harmony, b, id, pa.Prefixes, onlyUnpatch);
            }
            if (post)
            {
                UnpatchCheckList(harmony, b, id, pa.Postfixes, onlyUnpatch);
            }
            if (trans)
            {
                UnpatchCheckList(harmony, b, id, pa.Transpilers, onlyUnpatch);
            }
        }
示例#11
0
        public static bool Load(UnityModManager.ModEntry modEntry)
        {
            Main.Logger   = modEntry.Logger;
            Main.settings = UnityModManager.ModSettings.Load <Main.Settings>(modEntry);
            HarmonyInstance harmonyInstance = HarmonyInstance.Create(modEntry.Info.Id);

            harmonyInstance.PatchAll(Assembly.GetExecutingAssembly());
            MethodInfo method    = typeof(ActorMenu).GetMethod("Awake", BindingFlags.Instance | BindingFlags.NonPublic);
            Patches    patchInfo = harmonyInstance.GetPatchInfo(method);
            ReadOnlyCollection <Patch> readOnlyCollection = (patchInfo != null) ? patchInfo.Postfixes : null;

            if (readOnlyCollection == null || readOnlyCollection.Count == 0)
            {
                HarmonyMethod harmonyMethod = new HarmonyMethod(typeof(ActorMenu_Awake_Patch), "Postfix", new Type[]
                {
                    typeof(ActorMenu)
                });
                harmonyInstance.Patch(method, null, harmonyMethod, null);
            }
            modEntry.OnToggle  = new Func <UnityModManager.ModEntry, bool, bool>(Main.OnToggle);
            modEntry.OnGUI     = new Action <UnityModManager.ModEntry>(Main.OnGUI);
            modEntry.OnSaveGUI = new Action <UnityModManager.ModEntry>(Main.OnSaveGUI);
            return(true);
        }
示例#12
0
        /// <summary>
        /// Produces a human-readable list of all patched methods and their respective patches.
        /// </summary>
        /// <param name="instance">A HarmonyInstance that can be queried for patch information.</param>
        public static string DescribePatchedMethods(HarmonyInstance instance)
        {
            try {
                IEnumerable <MethodBase> patchedMethods;
                try {
                    patchedMethods = instance.GetPatchedMethods();
                } catch (Exception e) {
                    return("Could not retrieve patched methods from the Harmony library:\n" + e);
                }
                var methodList = patchedMethods.ToList();
                // generate method name strings so we can sort the patches alphabetically
                var namedMethodList = new List <NameMethodPair>(methodList.Count);
                foreach (var method in methodList)
                {
                    if (method == null)
                    {
                        continue;
                    }
                    string methodName;
                    if (method.DeclaringType != null)
                    {
                        methodName = string.Concat(method.DeclaringType.Name, ".", method.Name);
                    }
                    else
                    {
                        methodName = method.Name;
                    }
                    namedMethodList.Add(new NameMethodPair(methodName, method));
                }
                if (namedMethodList.Count == 0)
                {
                    return("No patches have been reported.");
                }
                // sort patches by patched method name
                namedMethodList.Sort((m1, m2) => string.Compare(m1.MethodName, m2.MethodName, StringComparison.Ordinal));

                var builder = new StringBuilder();
                foreach (var pair in namedMethodList)
                {
                    // write patched method
                    builder.Append(pair.MethodName);
                    builder.Append(": ");
                    // write patches
                    var patches = instance.GetPatchInfo(pair.Method);
                    if (HasActivePatches(patches))
                    {
                        // write prefixes
                        if (patches.Prefixes != null && patches.Prefixes.Count > 0)
                        {
                            builder.Append("PRE: ");
                            AppendPatchList(patches.Prefixes, builder);
                        }
                        // write postfixes
                        if (patches.Postfixes != null && patches.Postfixes.Count > 0)
                        {
                            EnsureEndsWithSpace(builder);
                            builder.Append("post: ");
                            AppendPatchList(patches.Postfixes, builder);
                        }
                        // write transpilers
                        if (patches.Transpilers != null && patches.Transpilers.Count > 0)
                        {
                            EnsureEndsWithSpace(builder);
                            builder.Append("TRANS: ");
                            AppendPatchList(patches.Transpilers, builder);
                        }
                    }
                    else
                    {
                        builder.Append("(no patches)");
                    }
                    builder.AppendLine();
                }
                return(builder.ToString());
            } catch (Exception e) {
                return("An exception occurred while collating patch data:\n" + e);
            }
        }
示例#13
0
        public void Disable(UnityModManager.ModEntry modEntry, bool unpatch = false)
        {
            DateTime startTime = DateTime.Now;

            Debug($"[{DateTime.Now - startTime:ss':'ff}] Disabling.");

            // using try-catch to prevent the progression being disrupt by exceptions
            try
            {
                if (Enabled && _eventHandler != null)
                {
                    Debug($"[{DateTime.Now - startTime:ss':'ff}] Raising events: 'OnDisable'");
                    foreach (IModEventHandler handler in _eventHandler)
                    {
                        handler.HandleModDisable();
                    }
                }
            }
            catch (Exception e)
            {
                Error(e.ToString());
            }

            _eventHandler = null;

            if (unpatch)
            {
                HarmonyInstance harmonyInstance = HarmonyInstance.Create(modEntry.Info.Id);
                foreach (MethodBase method in harmonyInstance.GetPatchedMethods().ToList())
                {
                    Patches      patchInfo = harmonyInstance.GetPatchInfo(method);
                    List <Patch> patches   = patchInfo.Transpilers.Concat(patchInfo.Postfixes).Concat(patchInfo.Prefixes)
                                             .Where(patch => patch.owner == modEntry.Info.Id).ToList();
                    if (patches.Any())
                    {
                        Debug($"[{DateTime.Now - startTime:ss':'ff}] Unpatching: {patches.First().patch.DeclaringType.DeclaringType?.Name}.{method.DeclaringType.Name}.{method.Name}");
                        foreach (Patch patch in patches)
                        {
                            try
                            {
                                harmonyInstance.Unpatch(method, patch.patch);
                            }
                            catch (Exception e)
                            {
                                Error(e.ToString());
                            }
                        }
                    }
                }
                Patched = false;
            }

            modEntry.OnSaveGUI -= HandleSaveGUI;

            Mod      = null;
            Settings = null;

            Enabled = false;

            Debug($"[{DateTime.Now - startTime:ss':'ff}] Disabled.");
        }
示例#14
0
 private static void addMethodToRemoveListIfPatchedByMe(MethodBase patchedMethod, List <MethodBase> methodsToRemove)
 {
     harmony.GetPatchInfo(patchedMethod).Owners.DoIf(isPatchedByMe, delegate {
         methodsToRemove.Add(patchedMethod);
     });
 }