private ModLoader.ModInfo _LoadOrIgnoreIfBlacklisted(string mods_dir_entry, HashSet <string> blacklist) { var filename = Path.GetFileName(mods_dir_entry); if (blacklist.Contains(mods_dir_entry)) { Logger.Info($"Refusing to load blacklisted mod: {filename}"); return(null); } Logger.Info($"Loading mod: {filename}"); try { return(ModLoader.Load(mods_dir_entry)); } catch (Exception e) { Logger.Error($"Exception while loading mod {filename}: [{e.GetType().Name}] {e.Message}"); ErrorLoadingMod.Invoke(filename, e); foreach (var l in e.StackTrace.Split('\n')) { Logger.ErrorIndent(l); } if (e.InnerException != null) { Logger.ErrorIndent($"Inner exception: [{e.InnerException.GetType().Name}] {e.InnerException.Message}"); foreach (var l in e.InnerException.StackTrace.Split('\n')) { Logger.ErrorIndent(l); } } } return(null); }
public void Unload(ModInfo info) { UnloadAll(info.EmbeddedMods); Logger.Info($"Unloading mod {info.Name}"); if (info.HasScript) { try { info.Triggers.InvokeUnloaded(); } catch (LuaException e) { Logger.Error(e.Message); LuaError.Invoke(info, LuaEventMethod.Unloaded, e); for (int i = 0; i < e.TracebackArray.Length; i++) { Logger.ErrorIndent(" " + e.TracebackArray[i]); } } } info.Dispose(); info.EmbeddedMods = new List <ModInfo>(); PostUnloadMod.Invoke(info); }
public void ExecuteCommandAndPrintResult(string cmd) { if (PrintUsedCommand) { PrintLine("> " + cmd, color: new Color(87 / 255f, 87 / 255f, 87 / 255f)); } try { PrintLine(ExecuteCommand(cmd)); } catch (Exception e) { PrintError("Exception while executing command:"); PrintError(e.Message); PrintError("More detailed info in the log."); Logger.Error($"Exception while running command '{cmd}':"); Logger.Error(e.Message); var stlines = e.StackTrace.Split('\n'); for (int i = 0; i < stlines.Length; i++) { Logger.ErrorIndent(stlines[i]); } } }
/// <summary> /// Loads a mod. /// </summary> /// <param name="info">Preloaded mod info.</param> /// <param name="tree_history">Hash set of mod IDs in the dependency tree. This is used to detect cyclic dependencies.</param> internal static void LoadMod(ModInfo info, HashSet <string> tree_history = null) { Logger.Debug($"Loading: {info.Config.ID}"); CurrentLoadingModID = null; CurrentLoadingModName = null; var config = info.Config; if (Mods.ContainsKey(config.ID)) { return; // already loaded! } CurrentLoadingModID = config.ID; CurrentLoadingModName = config.Name; var dll_name = config.DLL ?? "mod.dll"; var dll_path = Path.Combine(info.Path, dll_name); if (!File.Exists(dll_path)) { throw new InvalidConfigException(config.ID, $"Tried loading mod '{config.ID}' but it doesn't have the specified DLL file {dll_name}."); } if (config.Depends != null) { if (tree_history == null) { tree_history = new HashSet <string>(); } tree_history.Add(config.ID); for (var i = 0; i < config.Depends.Length; i++) { var dep = config.Depends[i].Trim(); Logger.Debug($"'{config.ID}' dependency: '{dep}'"); ModInfo dep_info = null; if (!FlatModInfos.TryGetValue(dep, out dep_info)) { throw new MissingDependencyException(config.ID, dep); } if (tree_history != null && tree_history.Contains(dep)) { throw new CyclicDependencyException(config.ID, dep); } LoadMod(dep_info, tree_history); } } AppDomain.CurrentDomain.AssemblyResolve += GenerateModAssemblyResolver(info.Path); Assembly asm; using (FileStream f = File.OpenRead(dll_path)) { asm = AssemblyRelinker.GetRelinkedAssembly(config.ID, dll_name, dll_path, f); } if (asm == null) { throw new ModLoadException(config.ID, "Failed loading/relinking assembly"); } if (info.Config.ModType == ModConfig.Type.Library) { Logger.Debug($"Mod is a library; not creating any Mod instances"); return; } Logger.Debug($"Searching for Mod subclasses"); Type[] types = null; try { types = asm.GetTypes(); } catch (ReflectionTypeLoadException e) { Logger.Error($"Failed loading types from mod:"); if (e.LoaderExceptions == null) { Logger.ErrorIndent("(No loader exceptions)"); } else { for (int i = 0; i < e.LoaderExceptions.Length; i++) { var ex = e.LoaderExceptions[i]; Logger.ErrorIndent($"- [{ex.GetType().Name}] {ex.Message}"); } } return; } Logger.Debug($"{types.Length} type(s)"); for (int i = 0; i < types.Length; i++) { var type = types[i]; if (!typeof(Mod).IsAssignableFrom(type) || type.IsAbstract) { continue; } var mod_go = new GameObject($"Semi Mod '{config.ID}' GameObject"); UnityEngine.Object.DontDestroyOnLoad(mod_go); ModsStorageObjects.Add(mod_go); Mod mod_instance = (Mod)mod_go.AddComponent(type); Logger.Debug($"Type name: {mod_instance.GetType().FullName}"); mod_instance.Logger = new Logger(config.Name ?? config.ID); info.Instance = mod_instance; config.Instance = mod_instance; Mods[config.ID] = info; mod_instance.Info = info; mod_instance.Loaded(); } }