コード例 #1
0
 /// <summary>
 /// Required by classes that extend Gadget. Provides information about your Gadget.
 /// </summary>
 /// <param name="Name">The friendly name of this Gadget. Also used for registry names. Should not contain special characters.</param>
 /// <param name="RequiredOnClients">Whether multiplayer clients attempting to connect without this Gadget should be rejected.</param>
 /// <param name="EnableByDefault">Whether the Gadget should default to being enabled or not when first installed.</param>
 /// <param name="LoadAfter">The list of any and all Gadgets that this Gadget should load after, regardless of <paramref name="LoadPriority"></paramref></param>
 /// <param name="LoadBefore">The list of any and all Gadgets that this Gadget should load before, regardless of <paramref name="LoadPriority"></paramref></param>
 /// <param name="LoadPriority">The priority for loading your Gadget. Higher number means higher priority. Leave at 0 if you don't care.</param>
 /// <param name="Dependencies">The names of any and all other Gadgets that your Gadget is dependent upon. If they are not present, your Gadget will not be loaded, and if your Gadget has the same load priority as them, your Gadget will be guaranteed to load after them. May include version numbers with the syntax of \"ModName v1.0\". The level of precision used in the specified version number indicates the version specificity of the dependency.</param>
 /// <param name="AllowRuntimeReloading">Whether this Gadget can be reloaded at runtime. Gadget reloads will also cause the config to be reloaded. Defaults to true.</param>
 /// <param name="AllowConfigReloading">Whether this Gadget can have its config reloaded at runtime, without reloading the entire Gadget. Defaults to true.</param>
 /// <param name="GadgetVersionSpecificity">The point at which a difference between the mod versions of the host and client should flag an incompatibility.</param>
 /// <param name="GadgetCoreVersionSpecificity">The point at which a change to GadgetCore should flag this Gadget as incompatible.</param>
 /// <param name="TargetGCVersion">The version of GadgetCore your Gadget is made for. This is automatically assigned to the version of GadgetCore you are building with, so you should always leave this at default.</param>
 public GadgetAttribute(string Name, bool RequiredOnClients = true, bool EnableByDefault = true, string[] LoadAfter = null, string[] LoadBefore = null, int LoadPriority = 0, string[] Dependencies = null, bool AllowRuntimeReloading = true, bool AllowConfigReloading = true, VersionSpecificity GadgetVersionSpecificity = VersionSpecificity.MINOR, VersionSpecificity GadgetCoreVersionSpecificity = VersionSpecificity.MINOR, string TargetGCVersion = GadgetCoreAPI.RAW_VERSION)
 {
     this.Name = Name;
     this.RequiredOnClients            = RequiredOnClients;
     this.EnableByDefault              = EnableByDefault;
     this.LoadAfter                    = LoadAfter ?? new string[0];
     this.LoadBefore                   = LoadBefore ?? new string[0];
     this.LoadPriority                 = LoadPriority;
     this.Dependencies                 = Dependencies ?? new string[0];
     this.AllowRuntimeReloading        = AllowRuntimeReloading;
     this.AllowConfigReloading         = AllowConfigReloading;
     this.GadgetVersionSpecificity     = GadgetVersionSpecificity;
     this.GadgetCoreVersionSpecificity = GadgetCoreVersionSpecificity;
     this.TargetGCVersion              = TargetGCVersion;
 }
コード例 #2
0
        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;
                    if (valid && splitDependency.Length == 2)
                    {
                        string versionString     = splitDependency[1].Replace("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 = (VersionSpecificity)targetVersionNums.Length;
                        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;
                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
                            {
                                gadget.Gadget.HarmonyInstance.CreateClassProcessor(type).Patch();
                                patches++;
                            }
                            catch (Exception e)
                            {
                                Logger.LogError("Exception running patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': " + Environment.NewLine + e.ToString());
                            }
                        }
                    });
                    Logger.Log("Performed " + patches + " patches for " + gadget.Attribute.Name);
                }
                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.");
            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.modRegistering = gadget.Gadget.ModID;
                    gadget.Gadget.Initialize();
                }
                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.modRegistering = -1;
                }
            }
            Logger.Log("Done initializing Gadgets.");
            QueuedGadgets.Clear();
        }
コード例 #3
0
 /// <summary>
 /// Required by classes that extend GadgetMod. Provides information about your mod.
 /// </summary>
 /// <param name="Name">The friendly name of this mod. Also used for registry names. Should not contain special characters.</param>
 /// <param name="RequiredOnClients">Whether multiplayer clients attempting to connect without this mod should be rejected.</param>
 /// <param name="EnableByDefault">Whether the mod should default to being enabled or not when first installed.</param>
 /// <param name="LoadPriority">The priority for loading your mod. Higher number means higher priority. Leave at 0 if you don't care.</param>
 /// <param name="Dependencies">The names of any and all other Gadget mods that your mod is dependent upon. If they are not present, your mod will not be loaded, and if your mod has the same load priority as them, your mod will be guaranteed to load after them. May include version numbers with the syntax of \"ModName v1.0\". The level of precision used in the specified version number indicates the version specificity of the dependency.</param>
 /// <param name="ModVersionSpecificity">The point at which a difference between the mod versions of the host and client should flag an incompatibility.</param>
 /// <param name="GadgetVersionSpecificity">The point at which a change to GadgetCore should flag this mod as incompatible.</param>
 /// <param name="TargetGCVersion">The version of GadgetCore your mod is made for. This is automatically assigned to the version of GadgetCore you are building with, so you should always leave this at default.</param>
 public GadgetModAttribute(string Name, bool RequiredOnClients = true, bool EnableByDefault = true, int LoadPriority = 0, string[] Dependencies = null, VersionSpecificity ModVersionSpecificity = VersionSpecificity.MINOR, VersionSpecificity GadgetVersionSpecificity = VersionSpecificity.MINOR, string TargetGCVersion = GadgetCoreAPI.VERSION)
 {
     this.Name = Name;
     this.RequiredOnClients        = RequiredOnClients;
     this.EnableByDefault          = EnableByDefault;
     this.LoadPriority             = LoadPriority;
     this.Dependencies             = Dependencies ?? new string[0];
     this.ModVersionSpecificity    = ModVersionSpecificity;
     this.GadgetVersionSpecificity = GadgetVersionSpecificity;
     this.TargetGCVersion          = TargetGCVersion;
 }
コード例 #4
0
 public void UpdateInfo(Toggle toggle, int modIndex)
 {
     try
     {
         if (GadgetModConfigs.IsConfigMenuOpen(this.modIndex))
         {
             GadgetModConfigs.CloseConfigMenu(this.modIndex);
         }
         if (!File.Exists(UMFData.DisabledModsFile))
         {
             File.Create(UMFData.DisabledModsFile).Dispose();
         }
         this.toggle   = toggle;
         this.modIndex = modIndex;
         string[] disabledMods = File.ReadAllLines(UMFData.DisabledModsFile).Where(x => !string.IsNullOrEmpty(x)).ToArray();
         if (modIndex < GadgetMods.CountMods())
         {
             GadgetModInfo mod = GadgetMods.GetModInfo(modIndex);
             unpackButton.gameObject.SetActive(Directory.GetFiles(UMFData.ModsPath, mod.UMFName + "*.zip").Length > 0);
             enableUMFButton.interactable = !GadgetCore.dependencies.Any(x => !disabledMods.Contains(x.Key) && x.Value.Any(d => { string[] split = d.Split(' '); return(split[split.Length - 2].Equals(mod.UMFName)); }));
             if (mod.Attribute.Dependencies.All(x => GadgetMods.ListAllModInfos().Where(y => y.Mod.Enabled).Select(y => y.Attribute.Name).Contains(x) || GadgetMods.ListAllModInfos().Where(y => y.Mod.Enabled).Select(y => y.Mod.GetPreviousModNames()).Any(y => y.Contains(x))))
             {
                 enableButton.interactable = true;
                 string[][]      splitDependencies = mod.Attribute.Dependencies.Select(x => x.Split(' ')).Where(x => x.Length == 2).ToArray();
                 GadgetModInfo[] dependencies      = splitDependencies.Select(x => GadgetMods.ListAllModInfos().Where(y => y.Mod.Enabled).FirstOrDefault(y => y.Attribute.Name.Equals(x[0])) ?? GadgetMods.ListAllModInfos().Where(y => y.Mod.Enabled).First(y => y.Mod.GetPreviousModNames().Contains(x[0]))).ToArray();
                 for (int i = 0; i < dependencies.Length; i++)
                 {
                     int[] currentVersionNums = dependencies[i].Mod.GetModVersionString().Split('.').Select(x => int.Parse(x)).ToArray();
                     int[] targetVersionNums  = splitDependencies[i][1].TrimStart('v').Split('.').Select(x => int.Parse(x)).ToArray();
                     VersionSpecificity versionSpecificity = (VersionSpecificity)targetVersionNums.Length;
                     if (!((versionSpecificity == VersionSpecificity.MAJOR && currentVersionNums[0] == targetVersionNums[0] && (currentVersionNums[1] > targetVersionNums[1] || (currentVersionNums[1] == targetVersionNums[1] && (currentVersionNums[2] > targetVersionNums[2] || (currentVersionNums[2] == targetVersionNums[2] && currentVersionNums[3] >= targetVersionNums[3]))))) ||
                           (versionSpecificity == VersionSpecificity.MINOR && currentVersionNums[0] == targetVersionNums[0] && currentVersionNums[1] == targetVersionNums[1] && (currentVersionNums[2] > targetVersionNums[2] || (currentVersionNums[2] == targetVersionNums[2] && currentVersionNums[3] >= targetVersionNums[3]))) ||
                           (versionSpecificity == VersionSpecificity.NONBREAKING && currentVersionNums[0] == targetVersionNums[0] && currentVersionNums[1] == targetVersionNums[1] && currentVersionNums[2] == targetVersionNums[2] && currentVersionNums[3] >= targetVersionNums[3]) ||
                           (versionSpecificity == VersionSpecificity.BUGFIX && currentVersionNums[0] == targetVersionNums[0] && currentVersionNums[1] == targetVersionNums[1] && currentVersionNums[2] == targetVersionNums[2] && currentVersionNums[3] == targetVersionNums[3])))
                     {
                         enableButton.interactable = false;
                         break;
                     }
                 }
             }
             else
             {
                 enableButton.interactable = false;
             }
             configButton.interactable = GadgetModConfigs.GetConfigMenuObject(modIndex) != null;
             enableButton.GetComponentInChildren <Text>().text    = mod.Mod.Enabled ? "Disable Gadget" : "Enable Gadget";
             enableUMFButton.GetComponentInChildren <Text>().text = File.ReadAllLines(UMFData.DisabledModsFile).Any(x => x.Equals(mod.UMFName)) ? "Enable Mod" : "Disable Mod";
             string desc       = mod.Mod.GetModDescription();
             bool   isDescNull = desc == null;
             bool   isModInfo  = false;
             if (string.IsNullOrEmpty(desc))
             {
                 try
                 {
                     desc = File.ReadAllText(UMFData.ModInfosPath + "/" + mod.UMFName + "_v" + UMFMod.GetModVersion(mod.UMFName) + "_ModInfo.txt");
                 }
                 catch (Exception) { }
                 finally
                 {
                     if (string.IsNullOrEmpty(desc) || desc == "A UMF Mod(umodframework.com) for Roguelands")
                     {
                         desc = "This mod does not have a description, or a ModInfo file." + Environment.NewLine + (isDescNull ? "You should suggest to the mod author that they add a description." : "");
                     }
                     else
                     {
                         isModInfo = true;
                     }
                 }
             }
             descText.text =
                 mod.Attribute.Name + " v" + UMFMod.GetModVersion(mod.UMFName).ToString() + (mod.Mod.Enabled ? " (Enabled)" : " (Disabled)") + Environment.NewLine +
                 "UMF Mod: " + mod.UMFName + Environment.NewLine +
                 (GadgetCore.dependencies.ContainsKey(mod.UMFName) ? ("Dependencies: " + GadgetCore.dependencies[mod.UMFName].Aggregate((x, y) => x + ", " + y) + Environment.NewLine) : "") +
                 "Required on clients: " + (mod.Attribute.RequiredOnClients ? "Yes" : "No") + Environment.NewLine +
                 (isModInfo ? "UMF Mod Info: " : "Description: ") + UMFMod.GetModDescription(mod.UMFName) + Environment.NewLine + Environment.NewLine + desc;
         }
         else if (modIndex < GadgetMods.CountMods() + GadgetCore.nonGadgetMods.Count + GadgetCore.disabledMods.Count + GadgetCore.incompatibleMods.Count)
         {
             bool enabled = !File.ReadAllLines(UMFData.DisabledModsFile).Any(x => x.Equals(modIndex - GadgetMods.CountMods() < GadgetCore.nonGadgetMods.Count ? GadgetCore.nonGadgetMods[modIndex - GadgetMods.CountMods()] : modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count < GadgetCore.disabledMods.Count ? GadgetCore.disabledMods[modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count] : GadgetCore.incompatibleMods[modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count - GadgetCore.disabledMods.Count]));
             enableButton.GetComponentInChildren <Text>().text    = modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count >= 0 && modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count < GadgetCore.disabledMods.Count ? "Disabled" : "Not Gadget";
             enableUMFButton.GetComponentInChildren <Text>().text = enabled ? "Disable Mod" : "Enable Mod";
             string mod = modIndex - GadgetMods.CountMods() < GadgetCore.nonGadgetMods.Count ? GadgetCore.nonGadgetMods[modIndex - GadgetMods.CountMods()] : modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count < GadgetCore.disabledMods.Count ? GadgetCore.disabledMods[modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count] : GadgetCore.incompatibleMods[modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count - GadgetCore.disabledMods.Count];
             unpackButton.gameObject.SetActive(Directory.GetFiles(UMFData.ModsPath, mod + "*.zip").Length > 0);
             if (modIndex - GadgetMods.CountMods() < GadgetCore.nonGadgetMods.Count && GadgetCore.nonGadgetMods[modIndex - GadgetMods.CountMods()].Equals("GadgetCore"))
             {
                 enableUMFButton.interactable = false;
             }
             else
             {
                 enableUMFButton.interactable = !GadgetCore.dependencies.Any(x => !disabledMods.Contains(x.Key) && x.Value.Any(d => { string[] split = d.Split(' '); return(split[split.Length - 2].Equals(mod)); }));
             }
             enableButton.interactable = false;
             configButton.interactable = GadgetModConfigs.GetConfigMenuObject(modIndex) != null;
             string desc = null;
             try
             {
                 desc = File.ReadAllText(UMFData.ModInfosPath + "/" + mod + "_v" + UMFMod.GetModVersion(mod) + "_ModInfo.txt");
             }
             catch (Exception) { }
             finally
             {
                 if (string.IsNullOrEmpty(desc) || desc == "A UMF Mod(umodframework.com) for Roguelands")
                 {
                     desc = "This mod does not have a ModInfo file.";
                 }
                 descText.text =
                     mod + " v" + UMFMod.GetModVersion(mod).ToString() + (enabled ? " (Enabled)" : " (Disabled)") + Environment.NewLine +
                     (GadgetCore.dependencies.ContainsKey(mod) ? ("Dependencies: " + GadgetCore.dependencies[mod].Aggregate((x, y) => x + ", " + y) + Environment.NewLine) : "") +
                     "UMF Mod Info: " + UMFMod.GetModDescription(mod) + Environment.NewLine + Environment.NewLine + desc;
             }
         }
         else
         {
             string mod = GadgetCore.packedMods[modIndex - GadgetMods.CountMods() - GadgetCore.nonGadgetMods.Count - GadgetCore.disabledMods.Count - GadgetCore.incompatibleMods.Count];
             enableButton.interactable    = false;
             enableUMFButton.interactable = false;
             configButton.interactable    = false;
             unpackButton.interactable    = !unpackedMods.Contains(mod);
             unpackButton.gameObject.SetActive(true);
             descText.text = Path.GetFileName(mod) + Environment.NewLine + Environment.NewLine + "This mod is still packed in its .zip, and needs to be unpacked to run!";
         }
     }
     catch (Exception e)
     {
         descText.text = "An error occured while populating the info panel for this mod! Check GadgetCore.log for details.";
         GadgetCore.Log("An error occured while populating the info panel for the mod with the index " + modIndex + ": " + e.ToString());
     }
 }