diff --git a/BepInEx.Preloader/BepInEx.Preloader.csproj b/BepInEx.Preloader/BepInEx.Preloader.csproj index 94ee13f..dd5fdd8 100644 --- a/BepInEx.Preloader/BepInEx.Preloader.csproj +++ b/BepInEx.Preloader/BepInEx.Preloader.csproj @@ -54,9 +54,10 @@ + - + diff --git a/BepInEx.Preloader/Entrypoint.cs b/BepInEx.Preloader/Entrypoint.cs index bf7014a..6c9abc0 100644 --- a/BepInEx.Preloader/Entrypoint.cs +++ b/BepInEx.Preloader/Entrypoint.cs @@ -21,7 +21,10 @@ namespace BepInEx.Preloader private static void PreloaderMain() { if (Preloader.ConfigApplyRuntimePatches.Value) + { XTermFix.Apply(); + ConsoleSetOutFix.Apply(); + } Preloader.Run(); } diff --git a/BepInEx.Preloader/Logger/PreloaderConsoleListener.cs b/BepInEx.Preloader/Logger/PreloaderConsoleListener.cs new file mode 100644 index 0000000..ce3b680 --- /dev/null +++ b/BepInEx.Preloader/Logger/PreloaderConsoleListener.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using BepInEx.Configuration; +using BepInEx.Logging; + +namespace BepInEx.Preloader +{ + public class PreloaderConsoleListener : ILogListener + { + public static List LogEvents { get; } = new List(); + + public void LogEvent(object sender, LogEventArgs eventArgs) + { + if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) == 0) + return; + + LogEvents.Add(eventArgs); + } + + private static readonly ConfigEntry ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind( + "Logging.Console","LogLevels", + LogLevel.Fatal | LogLevel.Error | LogLevel.Message | LogLevel.Info, + "Which log levels to show in the console output."); + + public void Dispose() { } + } +} \ No newline at end of file diff --git a/BepInEx.Preloader/Logger/PreloaderLogWriter.cs b/BepInEx.Preloader/Logger/PreloaderLogWriter.cs deleted file mode 100644 index 267b907..0000000 --- a/BepInEx.Preloader/Logger/PreloaderLogWriter.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using BepInEx.Configuration; -using BepInEx.Logging; - -namespace BepInEx.Preloader -{ - public class PreloaderConsoleListener : ILogListener - { - public static List LogEvents { get; } = new List(); - - public static TextWriter StandardOut { get; set; } - protected PreloaderConsoleSource LoggerSource { get; set; } - - - public PreloaderConsoleListener(bool redirectConsole) - { - StandardOut = Console.Out; - - if (redirectConsole) - { - LoggerSource = new PreloaderConsoleSource(); - - Logger.Sources.Add(LoggerSource); - Console.SetOut(LoggerSource); - } - } - - public void LogEvent(object sender, LogEventArgs eventArgs) - { - if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) == 0) - return; - - LogEvents.Add(eventArgs); - - ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor()); - ConsoleDirectWrite(eventArgs.ToStringLine()); - ConsoleManager.SetConsoleColor(ConsoleColor.Gray); - } - - public void ConsoleDirectWrite(string value) - { - StandardOut.Write(value); - } - - public void ConsoleDirectWriteLine(string value) - { - StandardOut.WriteLine(value); - } - - public void Dispose() - { - if (LoggerSource != null) - { - Console.SetOut(StandardOut); - Logger.Sources.Remove(LoggerSource); - LoggerSource.Dispose(); - LoggerSource = null; - } - } - - private static readonly ConfigEntry ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind( - "Logging.Console","LogLevels", - LogLevel.Fatal | LogLevel.Error | LogLevel.Message | LogLevel.Info, - "Which log levels to show in the console output."); - } - - public class PreloaderConsoleSource : TextWriter, ILogSource - { - public override Encoding Encoding { get; } = Console.OutputEncoding; - - public string SourceName { get; } = "BepInEx Preloader"; - - public event EventHandler LogEvent; - - public override void Write(object value) - => LogEvent?.Invoke(this, new LogEventArgs(value, LogLevel.Info, this)); - - public override void Write(string value) - => Write((object)value); - - public override void WriteLine() { } - - public override void WriteLine(object value) - => Write(value); - - public override void WriteLine(string value) - => Write(value); - } -} \ No newline at end of file diff --git a/BepInEx.Preloader/Preloader.cs b/BepInEx.Preloader/Preloader.cs index 8533424..3fab8f4 100644 --- a/BepInEx.Preloader/Preloader.cs +++ b/BepInEx.Preloader/Preloader.cs @@ -42,8 +42,9 @@ namespace BepInEx.Preloader Logger.InitializeInternalLoggers(); Logger.Sources.Add(TraceLogSource.CreateSource()); - - PreloaderLog = new PreloaderConsoleListener(ConfigPreloaderCOutLogging.Value); + + Logger.Listeners.Add(new ConsoleLogListener()); + PreloaderLog = new PreloaderConsoleListener(); Logger.Listeners.Add(PreloaderLog); string consoleTile = $"BepInEx {typeof(Paths).Assembly.GetName().Version} - {Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().ProcessName)}"; @@ -85,11 +86,9 @@ namespace BepInEx.Preloader AssemblyPatcher.PatchAndLoad(Paths.ManagedPath); AssemblyPatcher.DisposePatchers(); - Logger.LogMessage("Preloader finished"); Logger.Listeners.Remove(PreloaderLog); - Logger.Listeners.Add(new ConsoleLogListener()); PreloaderLog.Dispose(); } diff --git a/BepInEx.Preloader/RuntimeFixes/ConsoleSetOutFix.cs b/BepInEx.Preloader/RuntimeFixes/ConsoleSetOutFix.cs new file mode 100644 index 0000000..050d59a --- /dev/null +++ b/BepInEx.Preloader/RuntimeFixes/ConsoleSetOutFix.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using HarmonyLib; + +namespace BepInEx.Preloader.RuntimeFixes +{ + internal static class ConsoleSetOutFix + { + private static AggregatedTextWriter aggregatedTextWriter; + + public static void Apply() + { + aggregatedTextWriter = new AggregatedTextWriter(Console.Out); + Console.SetOut(aggregatedTextWriter); + HarmonyLib.Harmony.CreateAndPatchAll(typeof(ConsoleSetOutFix)); + } + + [HarmonyPatch(typeof(Console), nameof(Console.SetOut))] + [HarmonyPrefix] + private static bool OnSetOut(TextWriter newOut) + { + aggregatedTextWriter.Add(newOut); + return false; + } + } + + internal class AggregatedTextWriter : TextWriter + { + public override Encoding Encoding { get; } = Encoding.UTF8; + + private List writers = new List(); + + public AggregatedTextWriter(params TextWriter[] initialWriters) + { + writers.AddRange(initialWriters.Where(w => w != null)); + } + + public void Add(TextWriter tw) + { + if (writers.Any(t => t == tw)) + return; + writers.Add(tw); + } + + public override void Flush() => writers.ForEach(w => w.Flush()); + + public override void Write(object value) => writers.ForEach(w => w.Write(value)); + public override void Write(string value) => writers.ForEach(w => w.Write(value)); + public override void Write(char value) => writers.ForEach(w => w.Write(value)); + + public override void WriteLine(object value) => writers.ForEach(w => w.WriteLine(value)); + public override void WriteLine(string value) => writers.ForEach(w => w.WriteLine(value)); + public override void WriteLine(char value) => writers.ForEach(w => w.WriteLine(value)); + } +} \ No newline at end of file diff --git a/BepInEx/Logging/ConsoleLogListener.cs b/BepInEx/Logging/ConsoleLogListener.cs index e8be39a..d0f67bb 100644 --- a/BepInEx/Logging/ConsoleLogListener.cs +++ b/BepInEx/Logging/ConsoleLogListener.cs @@ -13,7 +13,7 @@ namespace BepInEx.Logging if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) == 0) return; ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor()); - ConsoleManager.ConsoleStream?.Write(eventArgs.ToStringLine()); + Console.Write(eventArgs.ToStringLine()); ConsoleManager.SetConsoleColor(ConsoleColor.Gray); } diff --git a/BepInEx/Logging/UnityLogSource.cs b/BepInEx/Logging/UnityLogSource.cs index fe04cf3..359ec72 100644 --- a/BepInEx/Logging/UnityLogSource.cs +++ b/BepInEx/Logging/UnityLogSource.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Reflection; using UnityEngine; @@ -78,6 +79,8 @@ namespace BepInEx.Logging if (type == LogType.Exception) message += $"\nStack trace:\n{stackTrace}"; + + File.WriteAllText("unity.log", $"{message}\n"); InternalUnityLogMessage?.Invoke(null, new LogEventArgs(message, logLevel, null)); }