コード例 #1
0
        /// <summary>
        /// Sets the Enabled status of the mod with the given index.
        /// </summary>
        public static void SetEnabled(int index, bool enabled)
        {
            GadgetModInfo modInfo = GetModInfo(index);

            modInfo.Mod.Enabled = enabled;
            GadgetCoreConfig.enabledMods[modInfo.Attribute.Name] = enabled;
            GadgetCoreConfig.Update();
        }
コード例 #2
0
ファイル: Gadgets.cs プロジェクト: Dariuken/Gadget-Core
 private static bool SetEnabledInternal(GadgetInfo gadget, bool enabled)
 {
     try
     {
         if (gadget.Gadget.Enabled == enabled)
         {
             return(false);
         }
         bool wasBatchLoading = GadgetLoader.BatchLoading;
         GadgetLoader.BatchLoading = true;
         if (enabled)
         {
             if (gadget.Attribute.AllowRuntimeReloading)
             {
                 EnableDependencies(gadget);
                 RefreshAfters(gadget);
             }
         }
         else
         {
             DisableDependents(gadget);
         }
         GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = enabled;
         if (gadget.Attribute.AllowRuntimeReloading || !enabled)
         {
             gadget.Gadget.Enabled = enabled;
         }
         GadgetLoader.BatchLoading = wasBatchLoading;
         GadgetLoader.QueuedGadgets.Add(gadget);
         if (!GadgetLoader.BatchLoading)
         {
             if (enabled)
             {
                 if (gadget.Attribute.AllowRuntimeReloading)
                 {
                     GadgetLoader.EnableQueuedGadgets();
                 }
             }
             else
             {
                 GadgetLoader.DisableQueuedGadgets();
             }
             GadgetCoreConfig.Update();
         }
         return(true);
     }
     catch (Exception e)
     {
         GadgetLoader.Logger.LogError("Error " + (enabled ? "enabling" : "disabling") + " Gadget `" + gadget.Attribute.Name + "`: " + e);
         return(false);
     }
 }
コード例 #3
0
 /// <summary>
 /// Called whenever the config menu's contents are updated in some way. This will be called whenever a default component's value is changed.
 /// </summary>
 public override void Update()
 {
     base.Update();
     IniParser.WriteFile(ConfigFilePath, Ini);
     if (ConfigFileSection == "GadgetCore")
     {
         GadgetCoreConfig.Load();
         GadgetCore.CoreLogger.Log("Finished reloading config.");
     }
     if (autoReload != null)
     {
         if (autoReload.Name == ConfigFileSection)
         {
             GadgetCoreAPI.GetUMFAPI()?.SendCommand("cfgReload " + Path.GetFileNameWithoutExtension(ConfigFilePath));
         }
         autoReload.Gadgets.FirstOrDefault(x => x.Attribute.Name == ConfigFileSection && x.Attribute.AllowConfigReloading)?.Gadget.ReloadConfig();
     }
 }
コード例 #4
0
        /// <summary>
        /// Sets the Enabled status of the given mod. Note that this can be queried using GadgetMod.Enabled
        /// </summary>
        public static void SetEnabled(GadgetMod mod, bool enabled)
        {
            if (mod.Enabled == enabled)
            {
                return;
            }
            mod.Enabled = enabled;
            GadgetCoreConfig.enabledMods[mod.Name] = enabled;
            bool wasBatchLoading = GadgetLoader.BatchLoading;

            GadgetLoader.BatchLoading = true;
            if (!enabled)
            {
                foreach (GadgetInfo gadget in mod.LoadedGadgets)
                {
                    Gadgets.SetEnabled(gadget, false);
                }
            }
            GadgetLoader.BatchLoading = wasBatchLoading;
            GadgetCoreConfig.Update();
        }
コード例 #5
0
 /// <summary>
 /// Sets the Enabled status of the mod with the given name using <see cref="GetModInfo(string)"/>. Will throw a NullReferenceException if there is no mod with the given name.
 /// </summary>
 public static void SetEnabled(string name, bool enabled)
 {
     GetModInfo(name).Mod.Enabled       = enabled;
     GadgetCoreConfig.enabledMods[name] = enabled;
     GadgetCoreConfig.Update();
 }
コード例 #6
0
 /// <summary>
 /// Sets the Enabled status of the given mod. Note that this can be queried using GadgetMod.Enabled, although it will not apply until the game is restarted.
 /// </summary>
 public static void SetEnabled(GadgetModInfo mod, bool enabled)
 {
     mod.Mod.Enabled = enabled;
     GadgetCoreConfig.enabledMods[mod.Attribute.Name] = enabled;
     GadgetCoreConfig.Update();
 }
コード例 #7
0
ファイル: GadgetLoader.cs プロジェクト: SuperKael/Gadget-Core
        internal static void EnableQueuedGadgets()
        {
            List <GadgetInfo> preFilteredQueuedGadgets = QueuedGadgets;

            QueuedGadgets = new List <GadgetInfo>();
            foreach (GadgetInfo gadget in preFilteredQueuedGadgets)
            {
                bool valid = true;
                foreach (string dependency in gadget.Attribute.Dependencies)
                {
                    string[]   splitDependency  = dependency.Split(':');
                    GadgetInfo dependencyGadget = Gadgets.GetGadgetInfo(splitDependency[0]);
                    valid = dependencyGadget != null && dependencyGadget.Gadget.Enabled;
                    if (valid)
                    {
                        if (splitDependency.Length == 2)
                        {
                            string versionString     = splitDependency[1].TrimStart('v');
                            int[]  targetVersionNums = versionString.Split('.').Select(x => int.Parse(x)).ToArray();
                            if (targetVersionNums.Length > 4)
                            {
                                continue;
                            }
                            int[] actualVersionNums = dependencyGadget.Mod.Version.ToString().Split('.').Select(x => int.Parse(x)).ToArray();
                            if (targetVersionNums.Length != 4)
                            {
                                Array.Resize(ref targetVersionNums, 4);
                            }
                            if (actualVersionNums.Length != 4)
                            {
                                Array.Resize(ref actualVersionNums, 4);
                            }
                            valid = actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && (actualVersionNums[2] > targetVersionNums[2] || (actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3]));
                        }
                        else if (splitDependency.Length == 3)
                        {
                            string versionString     = splitDependency[1].TrimStart('v');
                            int[]  targetVersionNums = versionString.Split('.').Select(x => int.Parse(x)).ToArray();
                            if (targetVersionNums.Length > 4)
                            {
                                continue;
                            }
                            int[] actualVersionNums = dependencyGadget.Mod.Version.ToString().Split('.').Select(x => int.Parse(x)).ToArray();
                            VersionSpecificity versionSpecificity;
                            try
                            {
                                versionSpecificity = (VersionSpecificity)Enum.Parse(typeof(VersionSpecificity), splitDependency[2], true);
                            }
                            catch (ArgumentException)
                            {
                                Logger.LogWarning("Gadget " + gadget.Attribute.Name + " has an improperly-formatted dependency version string: " + dependency);
                                versionSpecificity = VersionSpecificity.MINOR;
                            }
                            if (targetVersionNums.Length != 4)
                            {
                                Array.Resize(ref targetVersionNums, 4);
                            }
                            if (actualVersionNums.Length != 4)
                            {
                                Array.Resize(ref actualVersionNums, 4);
                            }
                            valid = (versionSpecificity == VersionSpecificity.MAJOR && actualVersionNums[0] == targetVersionNums[0] && (actualVersionNums[1] > targetVersionNums[1] || (actualVersionNums[1] == targetVersionNums[1] && (actualVersionNums[2] > targetVersionNums[2] || (actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3]))))) ||
                                    (versionSpecificity == VersionSpecificity.MINOR && actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && (actualVersionNums[2] > targetVersionNums[2] || (actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3]))) ||
                                    (versionSpecificity == VersionSpecificity.NONBREAKING && actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3]) ||
                                    (versionSpecificity == VersionSpecificity.BUGFIX && actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] == targetVersionNums[3]);
                        }
                    }
                }
                if (valid)
                {
                    QueuedGadgets.Add(gadget);
                }
                else
                {
                    gadget.Gadget.Enabled = false;
                    GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false;
                    Gadgets.UnregisterGadget(gadget);
                    Logger.LogWarning("Aborted loading Gadget " + gadget.Attribute.Name + " due to missing dependencies.");
                }
            }
            Logger.Log("Loading Gadget configs...");
            foreach (GadgetInfo gadget in QueuedGadgets.ToList())
            {
                Logger.Log("Loading Config for Gadget '" + gadget.Attribute.Name + "'");
                try
                {
                    gadget.Gadget.LoadConfig();
                }
                catch (Exception e)
                {
                    gadget.Gadget.Enabled = false;
                    GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false;
                    Gadgets.UnregisterGadget(gadget);
                    QueuedGadgets.Remove(gadget);
                    Logger.LogError("Exception Loading Config For Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString());
                }
            }
            Logger.Log("Done loading Gadget configs.");
            Logger.Log("Preparing Gadgets for patching...");
            foreach (GadgetInfo gadget in QueuedGadgets.ToList())
            {
                Logger.Log("PrePatching Gadget '" + gadget.Attribute.Name + "'");
                try
                {
                    gadget.Gadget.HarmonyInstance = new Harmony(gadget.Mod.Name + "." + gadget.Attribute.Name + ".gadget");
                    gadget.Gadget.PrePatch();
                }
                catch (Exception e)
                {
                    gadget.Gadget.Enabled = false;
                    GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false;
                    Gadgets.UnregisterGadget(gadget);
                    QueuedGadgets.Remove(gadget);
                    Logger.LogError("Exception PrePatching Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString());
                }
            }
            Logger.Log("Done preparing Gadgets for patching.");
            Logger.Log("Patching Gadgets...");
            foreach (GadgetInfo gadget in QueuedGadgets.ToList())
            {
                int patches = 0, totalMethods = 0, errorPatching = 0, targetMissing = 0;
                try
                {
                    gadget.Mod.Assembly.GetExportedTypes().Do(delegate(Type type)
                    {
                        HarmonyGadgetAttribute attribute = type.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(HarmonyGadgetAttribute)) as HarmonyGadgetAttribute;
                        if (attribute?.Gadget == gadget.Attribute.Name && attribute.RequiredGadgets.All(x => Gadgets.GetGadget(x) != null))
                        {
                            try
                            {
                                List <MethodInfo> methods = gadget.Gadget.HarmonyInstance.CreateClassProcessor(type).Patch();
                                totalMethods += methods?.Count ?? 0;
                                if (methods == null || methods.Count == 0)
                                {
                                    Logger.Log("Skipping patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': Attribute target does not exist.");
                                    targetMissing++;
                                }
                                else
                                {
                                    patches++;
                                }
                            }
                            catch (Exception e)
                            {
                                if (e.InnerException == null || !e.InnerException.Message.EndsWith("returned an unexpected result: null"))
                                {
                                    Logger.LogError("Exception running patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': " + Environment.NewLine + e.ToString());
                                    errorPatching++;
                                }
                                else
                                {
                                    Logger.Log("Skipping patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': TargetMethod returned null.");
                                    targetMissing++;
                                }
                            }
                        }
                    });
                    Logger.Log("Performed " + patches + " patches for '" + gadget.Attribute.Name + "'" + (totalMethods > 0 ? $" ({totalMethods} total methods patched)" : string.Empty) + (errorPatching > 0 ? targetMissing > 0 ? $" ({errorPatching} skipped due to errors, {targetMissing} skipped due to missing targets)" : $" ({errorPatching} skipped due to errors)" : targetMissing > 0 ? $" ({targetMissing} skipped due to missing targets)" : string.Empty));
                }
                catch (Exception e)
                {
                    gadget.Gadget.Enabled = false;
                    GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false;
                    Gadgets.UnregisterGadget(gadget);
                    QueuedGadgets.Remove(gadget);
                    Logger.LogError("Exception patching Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString());
                }
            }
            Logger.Log("Done patching Gadgets.");
            bool logOverrideWarnings = false;

            foreach (MethodBase patchedMethod in Harmony.GetAllPatchedMethods())
            {
                HarmonyLib.Patches patches = Harmony.GetPatchInfo(patchedMethod);
                if (patches == null)
                {
                    continue;
                }
                Dictionary <string, string> owners = new Dictionary <string, string>();
                List <Patch> overridingPrefixes    = patches.Prefixes.Where(x => x.PatchMethod.ReturnType == typeof(bool) && (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverridesAttribute)) as HarmonyOverridesAttribute)?.Overrides.Length != 0).ToList();
                if (overridingPrefixes != null && overridingPrefixes.Count > 0)
                {
                    foreach (string ownerID in patches.Owners)
                    {
                        if (ownerID == GadgetCore.HarmonyInstance.Id)
                        {
                            owners[ownerID] = "GadgetCore";
                        }
                        else
                        {
                            string[] splitOwnerID = ownerID.Split('.');
                            if (splitOwnerID.Length == 3 && splitOwnerID[2] == "gadget")
                            {
                                GadgetMod  mod    = GadgetMods.GetModByName(splitOwnerID[0]);
                                GadgetInfo gadget = mod?.LoadedGadgets.SingleOrDefault(x => x.Attribute.Name == splitOwnerID[1]);
                                if (gadget != null)
                                {
                                    owners[ownerID] = $"'{splitOwnerID[1]}' from the mod {{{splitOwnerID[0]}}}";
                                }
                                else
                                {
                                    owners[ownerID] = $"Unrecognized patcher '{ownerID}'";
                                }
                            }
                            else
                            {
                                owners[ownerID] = $"Unrecognized patcher '{ownerID}'";
                            }
                        }
                    }
                    IEnumerable <Patch> problematicPrefixes = patches.Prefixes.Where(x => !overridingPrefixes.Contains(x) && (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Length != 0 && overridingPrefixes.Any(
                                                                                         p => x.owner != p.owner &&
                                                                                         (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Contains(p.owner) != true &&
                                                                                         (p.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverridesAttribute)) as HarmonyOverridesAttribute)?.Overrides.Contains(x.owner) != true &&
                                                                                         x.priority <= p.priority &&
                                                                                         !x.before.Contains(p.owner) &&
                                                                                         !p.after.Contains(x.owner)));
                    IEnumerable <Patch> problematicTranspilers = patches.Transpilers.Where(x => (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Length != 0 && overridingPrefixes.Any(
                                                                                               p => x.owner != p.owner &&
                                                                                               (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Contains(p.owner) != true &&
                                                                                               (p.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverridesAttribute)) as HarmonyOverridesAttribute)?.Overrides.Contains(x.owner) != true));
                    if (problematicPrefixes != null && problematicPrefixes.Any() || problematicTranspilers != null && problematicTranspilers.Any())
                    {
                        if (!logOverrideWarnings)
                        {
                            logOverrideWarnings = true;
                            Logger.LogWarning("Possibly problematic patch overrides detected!", false);
                        }
                        Logger.Log($"Patches to {patchedMethod.DeclaringType.FullName}.{patchedMethod.Name} by {overridingPrefixes.Select(x => owners[x.owner]).Concat()} may override the following patch{(problematicPrefixes.Count() + problematicTranspilers.Count() > 1 ? "es" : "")}:");
                        if (problematicPrefixes != null)
                        {
                            foreach (Patch patch in problematicPrefixes)
                            {
                                Logger.Log($" - Prefix from {owners[patch.owner]}");
                            }
                        }
                        if (problematicTranspilers != null)
                        {
                            foreach (Patch patch in problematicTranspilers)
                            {
                                Logger.Log($" - Transpiler from {owners[patch.owner]}");
                            }
                        }
                    }
                }
            }
            if (logOverrideWarnings)
            {
                Logger.Log("End of possibly problematic patch overrides.");
            }
            Logger.Log("Creating registries...");
            foreach (GadgetInfo gadget in QueuedGadgets.ToList())
            {
                if (gadget.Gadget.Enabled)
                {
                    foreach (Registry registry in gadget.Gadget.CreateRegistries())
                    {
                        GameRegistry.RegisterRegistry(registry);
                    }
                }
            }
            Logger.Log("Done creating registries.");
            Logger.Log("Initializing Gadgets...");
            foreach (GadgetInfo gadget in QueuedGadgets.ToList())
            {
                Logger.Log("Initializing Gadget '" + gadget.Attribute.Name + "'");
                try
                {
                    Registry.gadgetRegistering = gadget.Gadget.ModID;
                    gadget.Gadget.LoadInternal();
                }
                catch (Exception e)
                {
                    gadget.Gadget.Enabled = false;
                    GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false;
                    Gadgets.UnregisterGadget(gadget);
                    QueuedGadgets.Remove(gadget);
                    Logger.LogError("Exception Initializing Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString());
                }
                finally
                {
                    Registry.gadgetRegistering = -1;
                }
            }
            Logger.Log("Done initializing Gadgets.");
            QueuedGadgets.Clear();
            GadgetCoreConfig.Update();
        }