using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx.ConsoleUtil;
using UnityEngine;
namespace BepInEx.Logging
{
///
/// Logs entries using Unity specific outputs.
///
public class UnityLogWriter : BaseLogger
{
///
/// Writes a string specifically to the game output log.
///
/// The value to write.
public void WriteToLog(string value)
{
UnityEngine.UnityLogWriter.WriteStringToUnityLog(value);
}
protected void InternalWrite(string value)
{
Console.Write(value);
WriteToLog(value);
}
///
/// Logs an entry to the Logger instance.
///
/// The level of the entry.
/// The textual value of the entry.
public override void Log(LogLevel level, object entry)
{
Kon.ForegroundColor = level.GetConsoleColor();
base.Log(level, entry);
Kon.ForegroundColor = ConsoleColor.Gray;
}
public override void WriteLine(string value) => InternalWrite($"{value}\r\n");
public override void Write(char value) => InternalWrite(value.ToString());
public override void Write(string value) => InternalWrite(value);
///
/// Start listening to Unity's log message events and sending the messages to BepInEx logger.
///
public static void ListenUnityLogs()
{
Type application = typeof(Application);
EventInfo logEvent = application.GetEvent("logMessageReceived", BindingFlags.Public | BindingFlags.Static);
if (logEvent != null)
{
logEvent.AddEventHandler(null, new Application.LogCallback(OnUnityLogMessageReceived));
}
else
{
MethodInfo registerLogCallback = application.GetMethod("RegisterLogCallback", BindingFlags.Public | BindingFlags.Static);
registerLogCallback.Invoke(null, new object[] { new Application.LogCallback(OnUnityLogMessageReceived) });
}
}
private static void OnUnityLogMessageReceived(string message, string stackTrace, LogType type)
{
LogLevel logLevel = LogLevel.Message;
switch (type)
{
case LogType.Error:
case LogType.Assert:
case LogType.Exception:
logLevel = LogLevel.Error;
break;
case LogType.Warning:
logLevel = LogLevel.Warning;
break;
case LogType.Log:
default:
logLevel = LogLevel.Message;
break;
}
Logger.Log(logLevel, message);
if (type == LogType.Exception)
{
Logger.Log(logLevel, $"Stack trace:\n{stackTrace}");
}
}
}
}
namespace UnityEngine
{
internal sealed class UnityLogWriter
{
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern void WriteStringToUnityLog(string s);
}
}