private void LoadResources() { CanvasUtil.CreateFonts(); TrajanBold = CanvasUtil.TrajanBold; TrajanNormal = CanvasUtil.TrajanNormal; try { Arial = Font.CreateDynamicFontFromOSFont ( Font.GetOSInstalledFontNames().First(x => x.ToLower().Contains("arial")), 13 ); } catch { Logger.LogWarn("Unable to find Arial! Using Perpetua."); Arial = CanvasUtil.GetFont("Perpetua"); } if (TrajanBold == null || TrajanNormal == null || Arial == null) { Benchwarp.instance.LogError("Could not find game fonts"); } Assembly asm = Assembly.GetExecutingAssembly(); foreach (string res in asm.GetManifestResourceNames()) { if (!res.StartsWith("Benchwarp.Images.")) { continue; } try { using (Stream imageStream = asm.GetManifestResourceStream(res)) { byte[] buffer = new byte[imageStream.Length]; imageStream.Read(buffer, 0, buffer.Length); Texture2D tex = new Texture2D(1, 1); tex.LoadImage(buffer.ToArray()); string[] split = res.Split('.'); string internalName = split[split.Length - 2]; images.Add(internalName, tex); Benchwarp.instance.Log("Loaded image: " + internalName); } } catch (Exception e) { Benchwarp.instance.LogError("Failed to load image: " + res + "\n" + e); } } }
internal static void LogWarn(string message) => L.LogWarn(prefix + message);
/// <summary> /// Loads the mod by searching for assemblies in hollow_knight_Data\Managed\Mods\ /// </summary> public static void LoadMods() { if (Loaded) { return; } Logger.Log("[API] - Trying to load mods"); string path = string.Empty; if (SystemInfo.operatingSystem.Contains("Windows")) { path = Application.dataPath + "\\Managed\\Mods"; } else if (SystemInfo.operatingSystem.Contains("Mac")) { path = Application.dataPath + "/Resources/Data/Managed/Mods/"; } else if (SystemInfo.operatingSystem.Contains("Linux")) { path = Application.dataPath + "/Managed/Mods"; } else { Logger.LogWarn($"Operating system of {SystemInfo.operatingSystem} is not known. Unable to load mods."); } if (string.IsNullOrEmpty(path)) { Loaded = true; return; } foreach (string text2 in Directory.GetFiles(path, "*.dll")) { Logger.LogDebug("[API] - Loading assembly: " + text2); try { foreach (Type type in Assembly.LoadFile(text2).GetExportedTypes()) { if (IsSubclassOfRawGeneric(typeof(Mod <>), type)) { Logger.LogDebug("[API] - Trying to instantiate mod<T>: " + type); IMod mod = Activator.CreateInstance(type) as IMod; if (mod == null) { continue; } LoadedMods.Add((Mod)mod); } else if (!type.IsGenericType && type.IsClass && type.IsSubclassOf(typeof(Mod))) { Logger.LogDebug("[API] - Trying to instantiate mod: " + type); Mod mod2 = type.GetConstructor(new Type[0])?.Invoke(new object[0]) as Mod; if (mod2 == null) { continue; } LoadedMods.Add(mod2); } } } catch (Exception ex) { Logger.LogError("[API] - Error: " + ex); Errors.Add(string.Concat(text2, ": FAILED TO LOAD! Check ModLog.txt.")); } } foreach (IMod mod in LoadedMods.OrderBy(x => x.LoadPriority())) { try { LoadMod(mod, false); } catch (Exception ex) { Errors.Add(string.Concat(mod.GetName(), ": FAILED TO LOAD! Check ModLog.txt.")); Logger.LogError("[API] - Error: " + ex); } } //Clean out the ModEnabledSettings for any mods that don't exist. //Calling ToList means we are not working with the dictionary keys directly, preventing an out of sync error foreach (string modName in ModHooks.Instance.GlobalSettings.ModEnabledSettings.Keys.ToList()) { if (LoadedMods.All(x => x.GetName() != modName)) { ModHooks.Instance.GlobalSettings.ModEnabledSettings.Remove(modName); } } GameObject gameObject = new GameObject(); _draw = gameObject.AddComponent <ModVersionDraw>(); UnityEngine.Object.DontDestroyOnLoad(gameObject); UpdateModText(); Loaded = true; ModHooks.Instance.SaveGlobalSettings(); }
private static void UpdateModText() { StringBuilder builder = new StringBuilder(); builder.AppendLine("Modding API: " + ModHooks.Instance.ModVersion + (ModHooks.Instance.IsCurrent ? "" : " - New Version Available!")); foreach (string error in Errors) { builder.AppendLine(error); } // 56 you made me do this, I hope you're happy Dictionary <string, List <IMod> > modsByNamespace = new Dictionary <string, List <IMod> >(); foreach (IMod mod in LoadedMods) { try { if (!ModHooks.Instance.GlobalSettings.ModEnabledSettings[mod.GetName()]) { continue; } if (!ModVersionsCache.ContainsKey(mod.GetName())) { ModVersionsCache.Add(mod.GetName(), mod.GetVersion() + (mod.IsCurrent() ? string.Empty : " - New Version Available!")); } string ns = mod.GetType().Namespace; if (!modsByNamespace.TryGetValue(ns, out List <IMod> nsMods)) { nsMods = new List <IMod>(); modsByNamespace.Add(ns, nsMods); } nsMods.Add(mod); } catch (Exception e) { Logger.LogError($"[API] - Failed to obtain mod namespace:\n{e}"); } } foreach (string ns in modsByNamespace.Keys) { try { List <IMod> nsMods = modsByNamespace[ns]; if (nsMods == null || nsMods.Count == 0) { Logger.LogWarn("[API] - Namespace mod list empty, ignoring"); continue; } else if (nsMods.Count == 1) { builder.AppendLine($"{nsMods[0].GetName()} : {ModVersionsCache[nsMods[0].GetName()]}"); } else { builder.Append($"{ns} : "); for (int i = 0; i < nsMods.Count; i++) { builder.Append(nsMods[i].GetName() + (i == nsMods.Count - 1 ? Environment.NewLine : ", ")); if ((i + 1) % 4 == 0 && i < nsMods.Count - 1) { builder.Append(Environment.NewLine + "\t"); } } } } catch (Exception e) { Logger.LogError($"[API] - Failed to append mod name text:\n{e}"); } } _draw.drawString = builder.ToString(); }
public static void LoadMods() { if (loaded) { return; } if (!Directory.Exists(MODS_FOLDER)) { Directory.CreateDirectory(MODS_FOLDER); } if (!Directory.Exists($"{MODS_FOLDER}{Path.DirectorySeparatorChar}{RELINK_FOLDER}")) { Directory.CreateDirectory($"{MODS_FOLDER}{Path.DirectorySeparatorChar}{RELINK_FOLDER}"); } DirectoryInfo relinkInfo = new DirectoryInfo($"{MODS_FOLDER}{Path.DirectorySeparatorChar}{RELINK_FOLDER}"); relinkInfo.Attributes |= FileAttributes.Hidden; loadedMods = new List <Mod>(); string ModText = "Underhero Modding API - Version " + ModHooks.API_VERSION; //Init mods from dlls. GetFiles is case-insensitive foreach (string name in Directory.GetFiles(MODS_FOLDER, "*.dll")) { Logger.LogDebug($"[API] Loading mods from assembly: \"{name}\""); try { //Relinker.Combine(stream, Path.GetFileNameWithoutExtension(name)); Assembly asm = Assembly.LoadFile(name); foreach (Type type in asm.GetExportedTypes()) { if (type.IsSubclassOf(typeof(Mod))) { Mod mod = (Mod)Activator.CreateInstance(type); if (mod == null) { Logger.LogWarn($"[API] Could not instantiate mod \"{type}\" from file \"{name}\""); continue; } loadedMods.Add(mod); } } } catch (Exception e) { Logger.LogError($"[API] Failed to load mod: \"{name}\"\n{e}"); } } //Sort can't take a lambda for some reason, gotta use this messier OrderBy implementation loadedMods = loadedMods.OrderBy(mod => { try { return(mod.LoadPriority()); } catch (Exception e) { Logger.LogError($"[API] Failed to get load priority from mod: \"{mod.GetModNameSafe()}\"\n{e}"); return(Mod.DEFAULT_PRIORITY); } }).ToList(); List <Mod> failedInit = new List <Mod>(); foreach (Mod mod in loadedMods) { string name = mod.GetModNameSafe(); Logger.LogDebug($"[API] Attempting to initialize mod \"{name}\""); try { mod.Initialize(); Logger.Log($"[API] Mod \"{name}\" initialized"); ModText += "\n" + mod.GetModName() + " - Version: " + mod.GetVersion(); } catch (Exception e) { Logger.LogError($"[API] Failed to initialize mod \"{name}\"\n{e}"); failedInit.Add(mod); } } loadedMods.RemoveAll(mod => failedInit.Contains(mod)); GameObject gameObject = new GameObject(); _draw = gameObject.AddComponent <ModVersionDraw>(); UnityEngine.Object.DontDestroyOnLoad(gameObject); _draw.drawString = ModText; loaded = true; }
public static void LoadMods() { if (loaded) { return; } if (!Directory.Exists(MODS_FOLDER)) { Directory.CreateDirectory(MODS_FOLDER); } if (!Directory.Exists($"{MODS_FOLDER}{Path.DirectorySeparatorChar}{RELINK_FOLDER}")) { Directory.CreateDirectory($"{MODS_FOLDER}{Path.DirectorySeparatorChar}{RELINK_FOLDER}"); } DirectoryInfo relinkInfo = new DirectoryInfo($"{MODS_FOLDER}{Path.DirectorySeparatorChar}{RELINK_FOLDER}"); relinkInfo.Attributes |= FileAttributes.Hidden; loadedMods = new List <Mod>(); //Init mods from dlls. GetFiles is case-insensitive foreach (string name in Directory.GetFiles(MODS_FOLDER, "*.dll")) { Logger.LogDebug($"[API] Loading mods from assembly: \"{name}\""); try { using (FileStream stream = File.OpenRead(Path.GetFullPath(name))) { Assembly asm = Relinker.GetRelinkedAssembly(stream, Path.GetFileNameWithoutExtension(name)); foreach (Type type in asm.GetExportedTypes()) { if (type.IsSubclassOf(typeof(Mod))) { Mod mod = (Mod)Activator.CreateInstance(type); if (mod == null) { Logger.LogWarn($"[API] Could not instantiate mod \"{type}\" from file \"{name}\""); continue; } loadedMods.Add(mod); } } } } catch (Exception e) { Logger.LogError($"[API] Failed to load mod: \"{name}\"\n{e}"); } } //Sort can't take a lambda for some reason, gotta use this messier OrderBy implementation loadedMods = loadedMods.OrderBy(mod => { try { return(mod.LoadPriority()); } catch (Exception e) { Logger.LogError($"[API] Failed to get load priority from mod: \"{mod.GetModNameSafe()}\"\n{e}"); return(Mod.DEFAULT_PRIORITY); } }).ToList(); List <Mod> failedInit = new List <Mod>(); foreach (Mod mod in loadedMods) { string name = mod.GetModNameSafe(); Logger.LogDebug($"[API] Attempting to initialize mod \"{name}\""); try { mod.Init(); Logger.Log($"[API] Mod \"{name}\" initialized"); } catch (Exception e) { Logger.LogError($"[API] Failed to initialize mod \"{name}\"\n{e}"); failedInit.Add(mod); } } loadedMods.RemoveAll(mod => failedInit.Contains(mod)); loaded = true; }