private bool CheckDependencies(Dictionary <string, Mod> lookup) { foreach (var mod in lookup.Values) { var deps = mod.Info.Dependencies; if (deps is null) { continue; } foreach (var dep in deps) { // Try finding the installed dependency if (!lookup.TryGetValue(dep.Key, out var resolved)) { _logger.LogFatal($"Mod {mod} depends on {dep.Key} @ {dep.Value}, but it is not installed"); return(false); } // Check if the installed version satisfies the dependency request if (resolved.Info.Version.CompareByPrecedence(dep.Value) == -1) { _logger.LogFatal($"Mod {mod} depends on {resolved.Info.Name ?? resolved.Info.Guid} @ {dep.Value}, but version {resolved.Info.Version} is installed"); return(false); } } } return(true); }
public static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { try { parentLogger.LogInfo("On Scene Loaded" + scene.name); UnityEngine.Debug.Log("Loading Scene: " + scene.name); if (scene.name == "UI") { TextMeshProUGUI betaText = GetUITextByName("BETA"); if (betaText) { betaText.text = "INJECTED BUILD - unstable mods"; } } else { TextMeshProUGUI modListText = GetUITextByName("TextMeshPro Text"); if (modListText) { BepInPlugin bepInPlugin = (BepInPlugin)Attribute.GetCustomAttribute(ModdingUtils.parentPlugin.GetType(), typeof(BepInPlugin)); if (modListText.text.EndsWith("</size>")) { modListText.text += "\n\nMods Currently Installed:\n"; } modListText.text += "\n" + bepInPlugin.Name + " - " + bepInPlugin.Version; } } } catch (Exception ex) { parentLogger.LogFatal(ex); } }
public static void Finish() { try { PluginCache = GetPluginCache(); Harmony = new Harmony("QModManager.QModPluginGenerator"); Harmony.Patch( typeof(TypeLoader).GetMethod(nameof(TypeLoader.FindPluginTypes)).MakeGenericMethod(typeof(PluginInfo)), postfix: new HarmonyMethod(typeof(QModPluginGenerator).GetMethod(nameof(TypeLoaderFindPluginTypesPostfix)))); } catch (Exception ex) { Logger.LogFatal($"An exception occurred while attempting to generate BepInEx PluginInfos: {ex.Message}."); Logger.LogFatal($"Beginning stacktrace:"); Logger.LogFatal(ex.StackTrace); } }
public static void Initialize() { try { ApplyHarmonyPatches(); InitAssemblyResolver(); ApplyShims(); } catch (Exception ex) { Logger.LogFatal($"An exception occurred while attempting to apply Harmony shims: {ex.Message}."); Logger.LogFatal($"Beginning stacktrace:"); Logger.LogFatal(ex.StackTrace); } }
public static void LogF(object data, [CallerLineNumber] int i = 0, [CallerMemberName] string member = "") { logger.LogFatal(string.Format(Plugin.modName + " ::{0} :: Line: {1}, Method {2}", data, i, member)); }
private IEnumerator _HostUnsafe() { _serverLog.LogDebug("Starting server..."); var config = _config.Host; var binding = config.Binding; var ipv4 = binding.IPv4.Value; var ipv6 = binding.IPv6.Value; var port = binding.Port.Value; var localhost = new IPEndPoint(ipv4 == IPAddress.Any ? IPAddress.Loopback : ipv4, port); IPEndPoint publicEndPoint; { IPAddress publicAddress; { var getter = config.PublicBinding.GetAddress(); foreach (object o in getter._Run()) { yield return(o); } var result = getter.Result; if (!result.Key) { _serverLog.LogFatal($"Failed to get public IP address to host server with: {result.Value}"); yield break; } // Safe to parse, already checked by AddressGetter publicAddress = IPAddress.Parse(result.Value); } ushort publicPort = config.PublicBinding.Port.Value; if (publicPort == 0) { publicPort = port; } publicEndPoint = new IPEndPoint(publicAddress, publicPort); } float ups = 1 / Time.fixedDeltaTime; // 90 double tps = config.TickRate.Value; if (tps <= 0) { _serverLog.LogFatal("The configurable tick rate must be a positive value."); yield break; } if (tps > ups) { tps = ups; _serverLog.LogWarning($"The configurable tick rate ({tps:.00}) is greater than the local fixed update rate ({ups:.00}). The config will be ignored and the fixed update rate will be used instead; running a tick rate higher than your own fixed update rate has no benefits."); } double tickDeltaTime = 1 / tps; Server = new H3Server(_serverLog, _config.Host, _rng, _messages.Server, _messages.ChannelsCount, _version, tickDeltaTime, publicEndPoint); _serverLog.LogInfo($"Now hosting on {publicEndPoint}!"); ConnectLocal(localhost, Server.Secret, Server.HostKey); }
public void Init() { DontDestroyOnLoad(this); Extensions.UnityInjectorPath = Path.GetFullPath(UnityInjectorLocation.Value); if (!Directory.Exists(Extensions.UnityInjectorPath)) { Logger.LogInfo($"No UnityInjector path found in {Extensions.UnityInjectorPath}. Creating one..."); try { Directory.CreateDirectory(Extensions.UnityInjectorPath); Directory.CreateDirectory(Extensions.UserDataPath); } catch (Exception e) { Logger.LogFatal($"Failed to create UnityInjector folder! Error message: {e.Message}"); } Destroy(this); return; } managerObject = new GameObject("UnityInjector"); Logger.LogInfo("UnityInjector started"); string currentProcess = Process.GetCurrentProcess().ProcessName; var plugins = new List <Type>(); foreach (string pluginDll in Directory.GetFiles(Extensions.UnityInjectorPath, "*.dll")) { try { var pluginAssembly = Assembly.LoadFile(pluginDll); foreach (var type in pluginAssembly.GetTypes()) { if (type.IsAbstract || type.IsInterface || !typeof(PluginBase).IsAssignableFrom(type)) { continue; } var filterAttributes = (PluginFilterAttribute[])type.GetCustomAttributes(typeof(PluginFilterAttribute), false); if (filterAttributes.Length == 0 || filterAttributes.Select(attr => attr.ExeName) .Contains(currentProcess, StringComparer.InvariantCultureIgnoreCase)) { plugins.Add(type); var name = type.GetCustomAttributes(typeof(PluginNameAttribute), false).FirstOrDefault() as PluginNameAttribute; var version = type.GetCustomAttributes(typeof(PluginVersionAttribute), false).FirstOrDefault() as PluginVersionAttribute; Logger.LogInfo($"UnityInjector: loaded {name?.Name ?? pluginAssembly.GetName().Name} {version?.Version ?? pluginAssembly.GetName().Version.ToString()}"); } } } catch (Exception e) { Logger.LogError($"Failed to load {pluginDll}. Stack trace:\n{e}"); } } if (plugins.Count == 0) { Logger.LogInfo("UnityInjector: No plugins found!"); Destroy(managerObject); Destroy(this); return; } foreach (var plugin in plugins) { try { managerObject.AddComponent(plugin); } catch (Exception e) { Logger.LogError($"UnityInjector: Failed to initialize {plugin.Assembly.GetName().Name}\nError: {e}"); } } Logger.LogInfo("UnityInjector: All plugins loaded"); managerObject.SetActive(true); }
public static void LogF(object data) => logger.LogFatal(data);
public static void LogFatal(object log) { LogSource.LogFatal(log); }
public void CleanTranslationCache() { Logger.LogMessage("Attempting to clean translation cache, please be patient..."); var cache = GeBoAPI.Instance.AutoTranslationHelper.DefaultCache; if (cache == null) { Logger.LogError("Unable to access translation cache"); return; } var translations = GeBoAPI.Instance.AutoTranslationHelper.GetTranslations() ?? new Dictionary <string, string>(); var regexes = new List <Regex>(); var tmp = GeBoAPI.Instance.AutoTranslationHelper.GetRegisteredRegexes(); if (tmp != null) { regexes.AddRange(tmp.Select(s => new Regex(s))); } tmp = GeBoAPI.Instance.AutoTranslationHelper.GetRegisteredSplitterRegexes(); if (tmp != null) { regexes.AddRange(tmp.Select(s => new Regex(s))); } var newFile = GetWorkFileName(Path.GetDirectoryName(AutoTranslationsFilePath), Path.GetFileName(AutoTranslationsFilePath), "new"); var backupFile = GetWorkFileName(Path.GetDirectoryName(AutoTranslationsFilePath), Path.GetFileName(AutoTranslationsFilePath), "bak"); MoveReplaceFile(AutoTranslationsFilePath, backupFile); Logger.LogInfo("Reloading translations without existing cache file"); ReloadTranslations(); var completed = false; try { char[] splitter = { '=' }; var changed = 0; using (var outStream = File.Open(newFile, FileMode.CreateNew, FileAccess.Write)) using (var writer = new StreamWriter(outStream, Encoding.UTF8)) using (var inStream = File.Open(backupFile, FileMode.Open, FileAccess.Read)) using (var reader = new StreamReader(inStream, Encoding.UTF8)) { string line; while ((line = reader.ReadLine()) != null) { var parts = line.Split(splitter, StringSplitOptions.None); if (parts.Length == 2 && !parts[0].StartsWith("//", StringComparison.InvariantCulture)) { if (translations.ContainsKey(parts[0])) { Logger.LogInfo($"Removing cached line (static match): {line.TrimEnd()}"); changed++; continue; } if (regexes.Any(r => r.IsMatch(parts[0]))) { Logger.LogInfo($"Removing cached line (regex match): {line.TrimEnd()}"); changed++; continue; } } writer.WriteLine(line); } } if (changed > 0) { Logger.LogMessage($"Done. Removed {changed} entries from cache. Reloading translations."); MoveReplaceFile(newFile, AutoTranslationsFilePath); } else { Logger.LogMessage("Done. No changes made. Restoring/reloading translations"); MoveReplaceFile(backupFile, AutoTranslationsFilePath); } ReloadTranslations(); completed = true; } catch (Exception e) { Logger.LogFatal(e.Message); Logger.LogError(e.StackTrace); throw; } finally { if (!completed) { if (File.Exists(backupFile)) { Logger.LogWarning("Something unexpected happened. Restoring previous translation cache."); MoveReplaceFile(backupFile, AutoTranslationsFilePath); ReloadTranslations(); } } } }
public static void Start(string[] args) { var preloaderListener = new PreloaderConsoleListener(); Logger.Listeners.Add(preloaderListener); if (string.IsNullOrEmpty(ConfigEntrypointExecutable.Value)) { Log.Log(LogLevel.Fatal, $"Entry executable was not set. Please set this in your config before launching the application"); Program.ReadExit(); return; } var executablePath = Path.GetFullPath(ConfigEntrypointExecutable.Value); if (!File.Exists(executablePath)) { Log.Log(LogLevel.Fatal, $"Unable to locate executable: {ConfigEntrypointExecutable.Value}"); Program.ReadExit(); return; } Paths.SetExecutablePath(executablePath); Program.ResolveDirectories.Add(Paths.GameRootPath); foreach (var searchDir in Program.ResolveDirectories) { TypeLoader.SearchDirectories.Add(searchDir); } if (PlatformHelper.Is(Platform.Windows)) { AddDllDirectory(Paths.GameRootPath); SetDllDirectory(Paths.GameRootPath); } Logger.Sources.Add(TraceLogSource.CreateSource()); ChainloaderLogHelper.PrintLogInfo(Log); Log.Log(LogLevel.Info, $"CLR runtime version: {Environment.Version}"); AssemblyBuildInfo executableInfo, launcherInfo; using (var executableAssembly = AssemblyDefinition.ReadAssembly(executablePath)) executableInfo = AssemblyBuildInfo.DetermineInfo(executableAssembly); using (var launcherAssembly = AssemblyDefinition.ReadAssembly(typeof(NetPreloader).Assembly.Location)) launcherInfo = AssemblyBuildInfo.DetermineInfo(launcherAssembly); // we don't particularly care about AnyCPU here since the fallback bitness is almost never the case if (executableInfo.Is64Bit != launcherInfo.Is64Bit) { Log.LogError($"Game executable is {(executableInfo.Is64Bit ? "64" : "32")}-bit while BepInEx has been compiled as {(launcherInfo.Is64Bit ? "64" : "32")}-bit. Expect crashes"); } if (executableInfo.NetFrameworkVersion != launcherInfo.NetFrameworkVersion || executableInfo.AssemblyFrameworkType != launcherInfo.AssemblyFrameworkType) { Log.LogWarning($"Game executable has been compiled as {executableInfo}, while BepInEx has been compiled as {launcherInfo}. There may be issues within the game caused by this"); } Log.LogInfo($"Game executable build architecture: {executableInfo}"); Log.LogInfo($"BepInEx launcher build architecture: {launcherInfo}"); Log.Log(LogLevel.Message, "Preloader started"); Assembly entrypointAssembly; using (var assemblyPatcher = new AssemblyPatcher()) { assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath); Log.Log(LogLevel.Info, $"{assemblyPatcher.PatcherContext.PatchDefinitions.Count} patcher definition(s) loaded"); assemblyPatcher.LoadAssemblyDirectories(new[] { Paths.GameRootPath }, new[] { "dll", "exe" }); Log.Log(LogLevel.Info, $"{assemblyPatcher.PatcherContext.AvailableAssemblies.Count} assemblies discovered"); assemblyPatcher.PatchAndLoad(); var assemblyName = AssemblyName.GetAssemblyName(executablePath); entrypointAssembly = assemblyPatcher.PatcherContext.LoadedAssemblies.Values.FirstOrDefault(x => x.FullName == assemblyName.FullName); foreach (var loadedAssembly in assemblyPatcher.PatcherContext.LoadedAssemblies) { // TODO: Need full paths for loaded assemblies var assemblyPath = Path.Combine(Paths.GameRootPath, loadedAssembly.Key); Log.LogDebug($"Registering '{assemblyPath}' as a loaded assembly"); AssemblyFixes.AssemblyLocations[loadedAssembly.Value.FullName] = assemblyPath; } if (entrypointAssembly != null) { Log.LogDebug("Found patched entrypoint assembly! Using it"); } else { Log.LogDebug("Using entrypoint assembly from disk"); entrypointAssembly = Assembly.LoadFrom(executablePath); } } Log.LogMessage("Preloader finished"); Logger.Listeners.Remove(preloaderListener); var chainloader = new NetChainloader(); chainloader.Initialize(); chainloader.Execute(); AssemblyFixes.Execute(entrypointAssembly); try { var argList = new List <object>(); var paramTypes = entrypointAssembly.EntryPoint.GetParameters(); if (paramTypes.Length == 1 && paramTypes[0].ParameterType == typeof(string[])) { argList.Add(args); } else if (paramTypes.Length == 1 && paramTypes[0].ParameterType == typeof(string)) { argList.Add(string.Join(" ", args)); } else if (paramTypes.Length != 0) { // Only other entrypoint signatures I can think of that .NET supports is Task / Task<int> // async entrypoints. That's a can of worms for another time though Log.LogFatal($"Could not figure out how to handle entrypoint method with this signature: {entrypointAssembly.EntryPoint.FullDescription()}"); return; } entrypointAssembly.EntryPoint.Invoke(null, argList.ToArray()); } catch (Exception ex) { Log.LogFatal($"Unhandled exception: {ex}"); } }
public static void LogF(object data, [CallerLineNumber] int i = 0, [CallerMemberName] string member = "") { logger.LogFatal(string.Format("TrinketsAndBaubles ::{0} :: Line: {1}, Method {2}", data, i, member)); }
public static void Fatal(object data) => _logSource.LogFatal(data);
public static void LogFatal(object data) { logger.LogFatal(data); }
internal static void LogFatal(object data) => _logSource.LogFatal(data);
public static void Start(string[] args) { if (ConfigEntrypointExecutable.Value == null) { Log.LogFatal($"Entry executable was not set. Please set this in your config before launching the application"); Program.ReadExit(); return; } string executablePath = Path.GetFullPath(ConfigEntrypointExecutable.Value); if (!File.Exists(executablePath)) { Log.LogFatal($"Unable to locate executable: {ConfigEntrypointExecutable.Value}"); Program.ReadExit(); return; } Paths.SetExecutablePath(executablePath); Program.ResolveDirectories.Add(Paths.GameRootPath); TypeLoader.SearchDirectories.Add(Paths.GameRootPath); Logger.Sources.Add(TraceLogSource.CreateSource()); ChainloaderLogHelper.PrintLogInfo(Log); Log.LogInfo($"CLR runtime version: {Environment.Version}"); Log.LogMessage("Preloader started"); Assembly entrypointAssembly; using (var assemblyPatcher = new AssemblyPatcher()) { assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath); Log.LogInfo($"{assemblyPatcher.PatcherPlugins.Count} patcher plugin(s) loaded"); assemblyPatcher.LoadAssemblyDirectory(Paths.GameRootPath, "dll", "exe"); Log.LogInfo($"{assemblyPatcher.AssembliesToPatch.Count} assemblies discovered"); assemblyPatcher.PatchAndLoad(); var assemblyName = AssemblyName.GetAssemblyName(executablePath); entrypointAssembly = assemblyPatcher.LoadedAssemblies.Values.FirstOrDefault(x => x.FullName == assemblyName.FullName); if (entrypointAssembly != null) { Log.LogDebug("Found patched entrypoint assembly! Using it"); } else { Log.LogDebug("Using entrypoint assembly from disk"); entrypointAssembly = Assembly.LoadFrom(executablePath); } } Log.LogMessage("Preloader finished"); var chainloader = new NetChainloader(); chainloader.Initialize(); chainloader.Execute(); AssemblyFix.Execute(entrypointAssembly); entrypointAssembly.EntryPoint.Invoke(null, new [] { args }); }
public void Critical(string str) { logSource.LogFatal(str); }