예제 #1
0
        internal static void GatherMods()
        {
            YamlFile <GuuMod>[] modFiles  = YamlUtils.GetModFiles();
            SortedSet <GuuMod>  loadOrder = new SortedSet <GuuMod>(new ModComparer());

            // Filter what is valid and invalid for load
            foreach (YamlFile <GuuMod> modFile in modFiles)
            {
                GuuMod mod = modFile.Read();

                // Check for mod ID
                if (mod.ID == null || mod.ID.Equals(string.Empty))
                {
                    GuuCore.LOGGER?.LogWarning($"Missing 'modID' key on file '{modFile.Info.FullName}' or the value is blank. Skipping mod!");
                    continue;
                }

                // Check if it is not example mod
                if (mod.ID.Equals(EXAMPLE_MOD_ID))
                {
                    GuuCore.LOGGER?.LogWarning($"Found example mod ID on file '{modFile.Info.FullName}', please change the ID of the mod. Skipping mod!");
                    continue;
                }

                // Check for assembly to load
                if (mod.AssemblyName == null || mod.AssemblyName.Equals(string.Empty))
                {
                    GuuCore.LOGGER?.LogWarning($"Missing 'assembly' key on file  {modFile.Info.FullName}' or the value is blank. Skipping mod!");
                    continue;
                }

                // Check for guu version to see if it can be loaded
                if (mod.GuuVersion != null && !mod.GuuVersion.Equals(string.Empty))
                {
                    if (!ValidateVersion(mod.GuuVersion, GuuCore.GUU_VERSION))
                    {
                        GuuCore.LOGGER?.LogWarning($"Guu version is outdated. Requires at least '{mod.GuuVersion}' but has '{GuuCore.GUU_VERSION}'. Skipping mod!");
                        continue;
                    }
                }

                mod.Info = modFile.Info;
                MODS.Add(mod.ID, null);
                loadOrder.Add(mod);
            }

            // Loads the mods and generates their mod information
            foreach (GuuMod mod in loadOrder)
            {
                string           modid        = mod.ID;
                string           mainAssembly = mod.AssemblyName;
                string           version      = mod.Version ?? ASSEMBLY_VERSION_TAG;
                bool             unsafeCheck  = mod.IsUnsafe;
                HashSet <string> required     = new HashSet <string>(mod.RequiredMods);

                EdenHarmony harmony = new EdenHarmony(modid);

                // Checks if all required mods are available
                foreach (string req in required)
                {
                    if (!MODS.ContainsKey(req))
                    {
                        throw new Exception($"Missing required mod '{req}' when loading '{modid}'");
                    }
                }

                // Checks and loads the main assembly
                FileInfo assembly = new FileInfo(Path.Combine(mod.Info.Directory.FullName, mainAssembly + GuuCore.DLL_EXTENSION));
                if (!assembly.Exists)
                {
                    throw new Exception($"Cannot load the main assembly '{mainAssembly}' for mod '{modid}'");
                }

                Assembly modAssembly = AssemblyUtils.LoadWithSymbols(assembly.FullName);
                harmony.LatePatchAll(modAssembly, !unsafeCheck ? AllowedPatchType.ALL : SAFE_PATCH);

                // Checks if version as {assemblyVersion} tag, and replaces it
                if (version.Equals(ASSEMBLY_VERSION_TAG))
                {
                    mod.Version = modAssembly.GetRuntimeVersion();
                }

                // Obtains the ModMain
                Type    mainType = modAssembly.GetTypes().Single(t => t.IsSubclassOf(typeof(ModMain)));
                ModMain main     = Activator.CreateInstance(mainType) as ModMain;

                main.Assembly    = modAssembly;
                main.Mod         = mod;
                main.Logger      = new ModLogger(modid);
                main.HarmonyInst = harmony;

                MOD_CONTEXTS.Add(modAssembly, new ModContext(main.Mod, main));

                // Finalizes the load process
                MODS[modid] = main;
            }

            // Loads all modules and registers them
            foreach (string modid in MODS.Keys)
            {
                ModMain         main        = MODS[modid];
                List <IModLoad> moduleMains = new List <IModLoad> {
                    main
                };

                foreach (ModModuleAttribute module in main.GetType().GetCustomAttributes <ModModuleAttribute>())
                {
                    string name   = module.moduleName;
                    string depID  = module.dependentID;
                    string depVer = module.dependentVersion;

                    // Checks if dependent is available, and if so if the version matches
                    if (!MODS.ContainsKey(depID))
                    {
                        continue;
                    }
                    if (!ValidateVersion(depVer, MODS[depID].Mod.Version))
                    {
                        continue;
                    }

                    // Checks and loads the assembly
                    FileInfo assembly = new FileInfo(Path.Combine(main.Mod.Info.Directory.FullName, name + GuuCore.DLL_EXTENSION));
                    if (!assembly.Exists)
                    {
                        throw new Exception($"Trying to load module '{name}' for mod '{modid}', but it wasn't found!");
                    }

                    Assembly moduleAssembly = AssemblyUtils.LoadWithSymbols(assembly.FullName);
                    main.HarmonyInst?.LatePatchAll(moduleAssembly, !main.Mod.IsUnsafe ? AllowedPatchType.ALL : SAFE_PATCH);

                    // Obtains the ModuleMain
                    Type       mainType   = moduleAssembly.GetTypes().Single(t => t.IsSubclassOf(typeof(ModuleMain)));
                    ModuleMain moduleMain = Activator.CreateInstance(mainType) as ModuleMain;

                    moduleMain.Assembly = moduleAssembly;
                    moduleMain.Main     = main;

                    MOD_CONTEXTS.Add(moduleAssembly, MOD_CONTEXTS[main.Assembly]);

                    // Finalizes the load process for this mod's modules
                    moduleMains.Add(moduleMain);
                }

                // Finalizes the load process for all modules
                main.Mod.Modules = moduleMains.ToArray();
            }

            // Executes all late patches
            foreach (ModMain main in MODS.Values)
            {
                main.HarmonyInst?.ExecuteLatePatches();
            }

            // Initializes the mods
            Init();

            // Preloads the mods
            PreLoad();

            // Triggers registration for all mods
            Register();
        }
예제 #2
0
 //+ CONSTRUCTOR
 internal ModContext(GuuMod mod, ModMain main)
 {
     Mod  = mod;
     Main = main;
 }