예제 #1
0
        public HarmonyStarter(ModContentPack content) : base(content)
        {
            Assembly terrainAssembly = Assembly.GetExecutingAssembly();
            string   DLLName         = terrainAssembly.GetName().Name;
            Version  loadedVersion   = terrainAssembly.GetName().Version;
            Version  laterVersion    = loadedVersion;

            List <ModContentPack> runningModsListForReading = LoadedModManager.RunningModsListForReading;

            foreach (ModContentPack mod in runningModsListForReading)
            {
                foreach (FileInfo item in from f in ModContentPack.GetAllFilesForMod(mod, "Assemblies/", (string e) => e.ToLower() == ".dll") select f.Value)
                {
                    var newAssemblyName = AssemblyName.GetAssemblyName(item.FullName);
                    if (newAssemblyName.Name == DLLName && newAssemblyName.Version > laterVersion)
                    {
                        laterVersion = newAssemblyName.Version;
                        Log.Error(String.Format("BiomesKit load order error detected. {0} is loading an older version {1} before {2} loads version {3}. Please put the BiomesKit, or BiomesCore modes above this one if they are active.",
                                                content.Name, loadedVersion, mod.Name, laterVersion));
                    }
                }
            }

            var harmony = new Harmony(HarmonyId);

            harmony.PatchAll(terrainAssembly);
        }
        /// <summary>
        /// Tries to find the file handle for a given mod assembly name.
        /// </summary>
        /// <remarks>This is a replacement for <see cref="Assembly.Location"/> mod assemblies are loaded from byte arrays.</remarks>
        /// <param name="assemblyName">The <see cref="AssemblyName.Name"/> of the assembly</param>
        /// <param name="contentPack">The content pack the assembly was presumably loaded from</param>
        /// <returns>Returns null if the file is not found</returns>
        public static FileInfo GetModAssemblyFileInfo(string assemblyName, [NotNull] ModContentPack contentPack)
        {
            if (contentPack == null)
            {
                throw new ArgumentNullException(nameof(contentPack));
            }
            const string AssembliesFolderName     = "Assemblies";
            var          expectedAssemblyFileName = $"{assemblyName}.dll";
            var          modAssemblyFolderFiles   = ModContentPack.GetAllFilesForMod(contentPack, AssembliesFolderName);

            return(modAssemblyFolderFiles.Values.FirstOrDefault(f => f.Name == expectedAssemblyFileName));
        }
        public List <string> LoadAllFiles(string folderPath)
        {
            var list = new List <string>();

            foreach (ModContentPack mod in LoadedModManager.RunningModsListForReading)
            {
                foreach (var f in ModContentPack.GetAllFilesForMod(mod, "Textures/" + folderPath))
                {
                    var path = f.Value.FullName;
                    if (path.EndsWith(".png"))
                    {
                        path = path.Replace("\\", "/");
                        path = path.Substring(path.IndexOf("/Textures/") + 10);
                        path = path.Replace(".png", "");
                        list.Add(path);
                    }
                }
            }
            return(list);
        }
예제 #4
0
        public IEnumerator DoTheThing()
        {
            MemoryUsageByMod.Clear();
            int count = CurrentMods.Count();
            int k     = 0;

            while (shouldStop || k < count)
            {
                if (shouldStop)
                {
                    yield return(null);

                    continue;
                }
                var mod = CurrentMods.ElementAt(k);
                MemoryUsageByMod.Add(mod, 0);
                Dictionary <string, FileInfo> allFilesForMod = ModContentPack.GetAllFilesForMod(mod, GenFilePaths.ContentPath <Texture2D>(), (ModContentLoader <Texture2D> .IsAcceptableExtension));
                int i = 0;
                while (shouldStop || i < allFilesForMod.Count)
                {
                    if (shouldStop)
                    {
                        yield return(null);

                        continue;
                    }
                    var pair = allFilesForMod.ElementAt(i);
                    MemoryUsageByMod[mod] += StaticTools.TextureSize(new VirtualFileWrapper(pair.Value));
                    i++;
                    if (i % 3 == 0)
                    {
                        yield return(null);
                    }
                }

                LargestModSize = MemoryUsageByMod[mod] > LargestModSize ? MemoryUsageByMod[mod] : LargestModSize;
                k++;
            }
            shouldRecalc = false;
            GraphicSetter.settings.CausedMemOverflow = MEMOVERFLOW;
        }
예제 #5
0
        public RIMMSAssemble(ModContentPack content) : base(content)
        {
            //Log.Message("starting rimmsassemble");

            //moving the new handler to the front since rimworlds handler is bugged and breaks the processing
            EventInfo           ei  = typeof(AppDomain).GetEvent("AssemblyResolve");
            FieldInfo           fi  = typeof(AppDomain).GetField("AssemblyResolve", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            ResolveEventHandler eh  = fi.GetValue(AppDomain.CurrentDomain) as ResolveEventHandler;
            List <Delegate>     lst = new List <Delegate>(eh.GetInvocationList());

            foreach (Delegate del in lst)
            {
                ei.GetRemoveMethod().Invoke(AppDomain.CurrentDomain, new object[] { del });
            }

            ResolveEventHandler reh = (object sender, ResolveEventArgs args) => {
                if (args.Name.IndexOf(" Version=") < 0)
                {
                    return(null);
                }

                //Log.Message("Custom assembly resolver: "+sender+" "+args+" "+args.Name);

                try {
                    AssemblyName an = new AssemblyName(args.Name);
                    an.Version = null;
                    return(Assembly.Load(an));
                } catch (Exception exception) {
                    Log.Error(exception.Message);
                }
                return(null);
            };

            AppDomain.CurrentDomain.AssemblyResolve += reh;

            foreach (Delegate del in lst)
            {
                ei.GetAddMethod().Invoke(AppDomain.CurrentDomain, new object[] { del });
            }

            //At this point assemblies that do not have types whose definition is not dependant on other assemblies will work.
            //However if a class is defined with a type dependancy the assembly loading crashed during earlier AssemblyIsUsable.
            //Therefore those assemblies must be renamed and only loaded after the assembly resolver is in place.
            //This also means we must take over the mod loading loop to ensure mods are loaded in proper order since assemblies are no longer loaded in order.
            List <Type> allExistingModClasses = new List <Type>(typeof(Mod).InstantiableDescendantsAndSelf());
            Dictionary <Assembly, ModContentPack> loadedAssemblies = new Dictionary <Assembly, ModContentPack>();
            MethodInfo miAssemblyIsUsable = typeof(ModAssemblyHandler).GetMethod("AssemblyIsUsable", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (ModContentPack modContentPack in LoadedModManager.RunningMods)
            {
                ModAssemblyHandler            ass = modContentPack.assemblies;
                Dictionary <string, FileInfo> assFilesInAssemblyFolder = ModContentPack.GetAllFilesForMod(modContentPack, "Assemblies/", s => s.ToLower() == ".ass");
                if (assFilesInAssemblyFolder == null || assFilesInAssemblyFolder.Count == 0)
                {
                    continue;
                }
                foreach (FileInfo fileInfo in assFilesInAssemblyFolder.Values)
                {
                    Assembly assembly = null;
                    try {
                        byte[]   rawAssembly = File.ReadAllBytes(fileInfo.FullName);
                        string   fileName    = Path.Combine(fileInfo.DirectoryName, Path.GetFileNameWithoutExtension(fileInfo.FullName)) + ".pdb";
                        FileInfo fileInfo2   = new FileInfo(fileName);
                        if (fileInfo2.Exists)
                        {
                            byte[] rawSymbolStore = File.ReadAllBytes(fileInfo2.FullName);
                            assembly = AppDomain.CurrentDomain.Load(rawAssembly, rawSymbolStore);
                        }
                        else
                        {
                            assembly = AppDomain.CurrentDomain.Load(rawAssembly);
                        }
                    } catch (Exception ex) {
                        Log.Error("Exception loading " + fileInfo.Name + ": " + ex.ToString(), false);
                        break;
                    }
                    Log.Message("testing assembly: " + assembly + " " + ass.loadedAssemblies.Contains(assembly));
                    if (assembly != null && !ass.loadedAssemblies.Contains(assembly))
                    {
                        if ((bool)miAssemblyIsUsable.Invoke(ass, new Object[] { assembly }))
                        {
                            ass.loadedAssemblies.Add(assembly);
                            loadedAssemblies.Add(assembly, modContentPack);
                            //Log.Message("Loading ass assembly: "+assembly.FullName);
                        }
                        else
                        {
                            Log.Message("Unusable ass assemble: " + assembly.FullName);
                        }
                    }
                }
            }

            if (loadedAssemblies.Count > 0)
            {
                //Reordering the mod classes and initializing them in order while filling runningModClasses will end the initial loop in createmodclasses() and load mods in the right order.
                Log.Message("Found ass assemblies. Creating new mod classes via custom loop.");
                List <Type>            modTypesSorted    = new List <Type>();
                List <ModContentPack>  modsOrdered       = LoadedModManager.RunningModsListForReading;
                Dictionary <Type, Mod> runningModClasses = (Dictionary <Type, Mod>) typeof(LoadedModManager).GetField("runningModClasses", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
                                                           .GetValue(null);
                foreach (Type type in typeof(Mod).InstantiableDescendantsAndSelf())
                {
                    if (!runningModClasses.ContainsKey(type) && !modTypesSorted.Contains(type) && type != typeof(RIMMSAssemble))
                    {
                        modTypesSorted.Add(type);
                    }
                }
                modTypesSorted.SortBy <Type, int>(t => modsOrdered.FirstIndexOf(m => m.assemblies.loadedAssemblies.Contains(t.Assembly)));

                List <ModContentPack> .Enumerator enumerator = modsOrdered.GetEnumerator();
                foreach (Type type in modTypesSorted)
                {
                    DeepProfiler.Start("Loading " + type + " mod class");
                    try
                    {
                        while (enumerator.MoveNext() && !enumerator.Current.assemblies.loadedAssemblies.Contains(type.Assembly))
                        {
                        }
                        if (enumerator.Current != null)
                        {
                            runningModClasses[type] = (Mod)Activator.CreateInstance(type, new object[] { enumerator.Current });
                        }
                        else
                        {
                            Log.Error("Failed to match ModContentPack to assembly!");
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(string.Concat(new object[]
                        {
                            "Error while instantiating a mod of type ",
                            type,
                            ": ",
                            ex
                        }), false);
                    }
                    finally
                    {
                        DeepProfiler.End();
                    }
                }
            }            /* else {
                          *     Log.Message("No new assemblies found, continuing with normal loading.");
                          * }*/
        }