Reformat project; apply code style

This commit is contained in:
ghorsington committed 2021-12-21 18:55:05 +02:00
1 parent 81141fcfc4
commit 4bb48c502e
30 files changed
+213 -172

No files matched your search

+10 -5
View File
@@ -52,7 +52,8 @@ public abstract class BaseChainloader<TPlugin>
if (string.IsNullOrEmpty(metadata.GUID) || !allowedGuidRegex.IsMatch(metadata.GUID)) if (string.IsNullOrEmpty(metadata.GUID) || !allowedGuidRegex.IsMatch(metadata.GUID))
{ {
Logger.Log(LogLevel.Warning, $"Skipping type [{type.FullName}] because its GUID [{metadata.GUID}] is of an illegal format."); Logger.Log(LogLevel.Warning,
$"Skipping type [{type.FullName}] because its GUID [{metadata.GUID}] is of an illegal format.");
return null; return null;
} }
@@ -196,7 +197,8 @@ public abstract class BaseChainloader<TPlugin>
{ {
if (loadedVersion != null) if (loadedVersion != null)
{ {
Logger.Log(LogLevel.Warning, $"Skipping [{pluginInfo}] because a newer version exists ({loadedVersion})"); Logger.Log(LogLevel.Warning,
$"Skipping [{pluginInfo}] because a newer version exists ({loadedVersion})");
continue; continue;
} }
@@ -210,7 +212,8 @@ public abstract class BaseChainloader<TPlugin>
if (invalidProcessName) if (invalidProcessName)
{ {
Logger.Log(LogLevel.Warning, $"Skipping [{pluginInfo}] because of process filters ({string.Join(", ", pluginInfo.Processes.Select(p => p.ProcessName).ToArray())})"); Logger.Log(LogLevel.Warning,
$"Skipping [{pluginInfo}] because of process filters ({string.Join(", ", pluginInfo.Processes.Select(p => p.ProcessName).ToArray())})");
continue; continue;
} }
@@ -340,7 +343,8 @@ public abstract class BaseChainloader<TPlugin>
invalidPlugins.Add(plugin.Metadata.GUID); invalidPlugins.Add(plugin.Metadata.GUID);
Plugins.Remove(plugin.Metadata.GUID); Plugins.Remove(plugin.Metadata.GUID);
Logger.Log(LogLevel.Error, $"Error loading [{plugin}]: {(ex is ReflectionTypeLoadException re ? TypeLoader.TypeLoadExceptionToString(re) : ex.ToString())}"); Logger.Log(LogLevel.Error,
$"Error loading [{plugin}]: {(ex is ReflectionTypeLoadException re ? TypeLoader.TypeLoadExceptionToString(re) : ex.ToString())}");
} }
} }
} }
@@ -366,7 +370,8 @@ public abstract class BaseChainloader<TPlugin>
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Log(LogLevel.Warning, $"Couldn't run Module constructor for {assembly.FullName}::{plugin.TypeName}: {e}"); Logger.Log(LogLevel.Warning,
$"Couldn't run Module constructor for {assembly.FullName}::{plugin.TypeName}: {e}");
} }
} }
+6 -3
View File
@@ -169,7 +169,8 @@ public static class TypeLoader
} }
catch (BadImageFormatException e) catch (BadImageFormatException e)
{ {
Logger.Log(LogLevel.Debug, $"Skipping loading {dll} because it's not a valid .NET assembly. Full error: {e.Message}"); Logger.Log(LogLevel.Debug,
$"Skipping loading {dll} because it's not a valid .NET assembly. Full error: {e.Message}");
} }
catch (Exception e) catch (Exception e)
{ {
@@ -228,7 +229,8 @@ public static class TypeLoader
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Log(LogLevel.Warning, $"Failed to load cache \"{cacheName}\"; skipping loading cache. Reason: {e.Message}."); Logger.Log(LogLevel.Warning,
$"Failed to load cache \"{cacheName}\"; skipping loading cache. Reason: {e.Message}.");
} }
return result; return result;
@@ -271,7 +273,8 @@ public static class TypeLoader
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Log(LogLevel.Warning, $"Failed to save cache \"{cacheName}\"; skipping saving cache. Reason: {e.Message}."); Logger.Log(LogLevel.Warning,
$"Failed to save cache \"{cacheName}\"; skipping saving cache. Reason: {e.Message}.");
} }
} }
-1
View File
@@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using BepInEx.Logging; using BepInEx.Logging;
namespace BepInEx.Configuration; namespace BepInEx.Configuration;
@@ -162,7 +162,8 @@ public static class TomlTypeConverter
if (converter == null) throw new ArgumentNullException(nameof(converter)); if (converter == null) throw new ArgumentNullException(nameof(converter));
if (CanConvert(type)) if (CanConvert(type))
{ {
Logger.Log(LogLevel.Warning, "Tried to add a TomlConverter when one already exists for type " + type.FullName); Logger.Log(LogLevel.Warning,
"Tried to add a TomlConverter when one already exists for type " + type.FullName);
return false; return false;
} }
+1 -1
View File
@@ -102,7 +102,7 @@ namespace BepInEx.ConsoleUtil
if (!flag) if (!flag)
return; return;
var num = bufferInfo.wAttributes; var num = bufferInfo.wAttributes;
num &= isBackground ? (short) -241 : (short) -16; num &= (short) (isBackground ? -241 : -16);
num = (short) ((ushort) num | (ushort) color); num = (short) ((ushort) num | (ushort) color);
SetConsoleTextAttribute(conOut, num); SetConsoleTextAttribute(conOut, num);
} }
@@ -6,42 +6,47 @@ using BepInEx.Logging;
namespace BepInEx.Core.Logging; namespace BepInEx.Core.Logging;
/// <summary> /// <summary>
/// Interpolated string handler for BepInEx <see cref="Logger"/>. This allows to conditionally skip logging certain messages and speed up logging in certain places. /// Interpolated string handler for BepInEx <see cref="Logger" />. This allows to conditionally skip logging certain
/// messages and speed up logging in certain places.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// The class isn't meant to be constructed manually. /// The class isn't meant to be constructed manually.
/// Instead, use <see cref="ManualLogSource.Log(BepInEx.Logging.LogLevel,BepInExLogInterpolatedStringHandler)"/> with string interpolation. /// Instead, use <see cref="ManualLogSource.Log(BepInEx.Logging.LogLevel,BepInExLogInterpolatedStringHandler)" /> with
/// string interpolation.
/// </remarks> /// </remarks>
[InterpolatedStringHandler] [InterpolatedStringHandler]
public class BepInExLogInterpolatedStringHandler public class BepInExLogInterpolatedStringHandler
{ {
// We can't use an array pool to support net35 builds, so default to StringBuilder
private readonly StringBuilder sb;
// See https://source.dot.net/#System.Private.CoreLib/DefaultInterpolatedStringHandler.cs,29 // See https://source.dot.net/#System.Private.CoreLib/DefaultInterpolatedStringHandler.cs,29
private const int GUESSED_LENGTH_PER_HOLE = 11; private const int GUESSED_LENGTH_PER_HOLE = 11;
// We can't use an array pool to support net35 builds, so default to StringBuilder
private readonly StringBuilder sb;
/// <summary> /// <summary>
/// Constructs a log handler. /// Constructs a log handler.
/// </summary> /// </summary>
/// <param name="literalLength">Length of the literal string.</param> /// <param name="literalLength">Length of the literal string.</param>
/// <param name="formattedCount">Number for formatted items.</param> /// <param name="formattedCount">Number for formatted items.</param>
/// <param name="logLevel">Log level the message belongs to.</param> /// <param name="logLevel">Log level the message belongs to.</param>
/// <param name="isEnabled">Whether this string should be logged.</param> /// <param name="isEnabled">Whether this string should be logged.</param>
public BepInExLogInterpolatedStringHandler(int literalLength, int formattedCount, LogLevel logLevel, out bool isEnabled) public BepInExLogInterpolatedStringHandler(int literalLength,
int formattedCount,
LogLevel logLevel,
out bool isEnabled)
{ {
Enabled = (logLevel & Logger.ListenedLogLevels) == LogLevel.None; Enabled = (logLevel & Logger.ListenedLogLevels) == LogLevel.None;
isEnabled = Enabled; isEnabled = Enabled;
sb = Enabled ? new StringBuilder(literalLength + (formattedCount * GUESSED_LENGTH_PER_HOLE)) : null; sb = Enabled ? new StringBuilder(literalLength + formattedCount * GUESSED_LENGTH_PER_HOLE) : null;
} }
/// <summary> /// <summary>
/// Whether the interpolation is enabled and string will be logged. /// Whether the interpolation is enabled and string will be logged.
/// </summary> /// </summary>
public bool Enabled { get; } public bool Enabled { get; }
/// <summary> /// <summary>
/// Appends a literal string to the interpolation. /// Appends a literal string to the interpolation.
/// </summary> /// </summary>
/// <param name="s">String to append.</param> /// <param name="s">String to append.</param>
public void AppendLiteral(string s) public void AppendLiteral(string s)
@@ -52,7 +57,7 @@ public class BepInExLogInterpolatedStringHandler
} }
/// <summary> /// <summary>
/// Appends a value to the interpolation. /// Appends a value to the interpolation.
/// </summary> /// </summary>
/// <param name="t">Value to append.</param> /// <param name="t">Value to append.</param>
/// <typeparam name="T">Type of the value to append.</typeparam> /// <typeparam name="T">Type of the value to append.</typeparam>
@@ -65,7 +70,7 @@ public class BepInExLogInterpolatedStringHandler
} }
/// <summary> /// <summary>
/// Append a formattable item. /// Append a formattable item.
/// </summary> /// </summary>
/// <param name="t">Item to append.</param> /// <param name="t">Item to append.</param>
/// <param name="format">Format to append with.</param> /// <param name="format">Format to append with.</param>
@@ -78,6 +83,19 @@ public class BepInExLogInterpolatedStringHandler
sb.Append(t?.ToString(format, null)); sb.Append(t?.ToString(format, null));
} }
/// <summary>
/// Append an IntPtr.
/// </summary>
/// <param name="t">Item to append.</param>
/// <param name="format">Format to append with.</param>
public void AppendFormatted(IntPtr t, string format)
{
if (!Enabled)
return;
sb.Append(t.ToString(format));
}
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() => sb?.ToString() ?? string.Empty; public override string ToString() => sb?.ToString() ?? string.Empty;
} }
-2
View File
@@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text;
using System.Threading; using System.Threading;
using Mono.Cecil;
namespace BepInEx.Logging; namespace BepInEx.Logging;
@@ -1,4 +1,5 @@
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace System.Runtime.CompilerServices; namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
+17 -17
View File
@@ -14,11 +14,19 @@ public static class Logger
private static readonly LogListenerCollection listeners; private static readonly LogListenerCollection listeners;
static Logger()
{
Sources = new LogSourceCollection();
listeners = new LogListenerCollection();
InternalLogSource = CreateLogSource("BepInEx");
}
/// <summary> /// <summary>
/// Log levels that are currently listened to by at least one listener. /// Log levels that are currently listened to by at least one listener.
/// </summary> /// </summary>
public static LogLevel ListenedLogLevels => listeners.activeLogLevels; public static LogLevel ListenedLogLevels => listeners.activeLogLevels;
/// <summary> /// <summary>
/// Collection of all log listeners that receive log events. /// Collection of all log listeners that receive log events.
/// </summary> /// </summary>
@@ -29,14 +37,6 @@ public static class Logger
/// </summary> /// </summary>
public static ICollection<ILogSource> Sources { get; } public static ICollection<ILogSource> Sources { get; }
static Logger()
{
Sources = new LogSourceCollection();
listeners = new LogListenerCollection();
InternalLogSource = CreateLogSource("BepInEx");
}
internal static void InternalLogEvent(object sender, LogEventArgs eventArgs) internal static void InternalLogEvent(object sender, LogEventArgs eventArgs)
{ {
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator Prevent extra allocations // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator Prevent extra allocations
@@ -53,14 +53,14 @@ public static class Logger
internal static void Log(LogLevel level, object data) => InternalLogSource.Log(level, data); internal static void Log(LogLevel level, object data) => InternalLogSource.Log(level, data);
/// <summary> /// <summary>
/// Logs an entry to the internal logger instance if any log listener wants the message. /// Logs an entry to the internal logger instance if any log listener wants the message.
/// </summary> /// </summary>
/// <param name="level">The level of the entry.</param> /// <param name="level">The level of the entry.</param>
/// <param name="logHandler">Log handler to resolve log from.</param> /// <param name="logHandler">Log handler to resolve log from.</param>
internal static void Log(LogLevel level, [InterpolatedStringHandlerArgument("level")] BepInExLogInterpolatedStringHandler logHandler) internal static void Log(LogLevel level,
{ [InterpolatedStringHandlerArgument("level")]
BepInExLogInterpolatedStringHandler logHandler) =>
InternalLogSource.Log(level, logHandler); InternalLogSource.Log(level, logHandler);
}
/// <summary> /// <summary>
/// Creates a new log source with a name and attaches it to <see cref="Sources" />. /// Creates a new log source with a name and attaches it to <see cref="Sources" />.
@@ -77,14 +77,14 @@ public static class Logger
private class LogListenerCollection : List<ILogListener>, ICollection<ILogListener> private class LogListenerCollection : List<ILogListener>, ICollection<ILogListener>
{ {
public LogLevel activeLogLevels = LogLevel.None; public LogLevel activeLogLevels = LogLevel.None;
void ICollection<ILogListener>.Add(ILogListener item) void ICollection<ILogListener>.Add(ILogListener item)
{ {
if (item == null) if (item == null)
throw new ArgumentNullException(nameof(item)); throw new ArgumentNullException(nameof(item));
activeLogLevels |= item.LogLevelFilter; activeLogLevels |= item.LogLevelFilter;
base.Add(item); base.Add(item);
} }
@@ -103,7 +103,7 @@ public static class Logger
foreach (var i in this) foreach (var i in this)
activeLogLevels |= i.LogLevelFilter; activeLogLevels |= i.LogLevelFilter;
return true; return true;
} }
} }
+3 -2
View File
@@ -34,12 +34,13 @@ public class ManualLogSource : ILogSource
/// <param name="data">Data to log.</param> /// <param name="data">Data to log.</param>
public void Log(LogLevel level, object data) => LogEvent?.Invoke(this, new LogEventArgs(data, level, this)); public void Log(LogLevel level, object data) => LogEvent?.Invoke(this, new LogEventArgs(data, level, this));
public void Log(LogLevel level, [InterpolatedStringHandlerArgument("level")] BepInExLogInterpolatedStringHandler logHandler) public void Log(LogLevel level,
[InterpolatedStringHandlerArgument("level")] BepInExLogInterpolatedStringHandler logHandler)
{ {
if (logHandler.Enabled) if (logHandler.Enabled)
LogEvent?.Invoke(this, new LogEventArgs(logHandler.ToString(), level, this)); LogEvent?.Invoke(this, new LogEventArgs(logHandler.ToString(), level, this));
} }
/// <summary> /// <summary>
/// Logs a message with <see cref="LogLevel.Fatal" /> level. /// Logs a message with <see cref="LogLevel.Fatal" /> level.
/// </summary> /// </summary>
+1 -1
View File
@@ -80,7 +80,7 @@ public static class Paths
public static string ProcessName { get; private set; } public static string ProcessName { get; private set; }
/// <summary> /// <summary>
/// List of directories from where Mono will search assemblies before assembly resolving is invoked. /// List of directories from where Mono will search assemblies before assembly resolving is invoked.
/// </summary> /// </summary>
public static string[] DllSearchPaths { get; private set; } public static string[] DllSearchPaths { get; private set; }
+5 -5
View File
@@ -25,7 +25,7 @@ public static class Utility
public static bool CLRSupportsDynamicAssemblies => CheckSRE(); public static bool CLRSupportsDynamicAssemblies => CheckSRE();
/// <summary> /// <summary>
/// An encoding for UTF-8 which does not emit a byte order mark (BOM). /// An encoding for UTF-8 which does not emit a byte order mark (BOM).
/// </summary> /// </summary>
public static Encoding UTF8NoBom { get; } = new UTF8Encoding(false); public static Encoding UTF8NoBom { get; } = new UTF8Encoding(false);
@@ -302,7 +302,7 @@ public static class Utility
} }
/// <summary> /// <summary>
/// Compute a MD5 hash of the given stream. /// Compute a MD5 hash of the given stream.
/// </summary> /// </summary>
/// <param name="stream">Stream to hash</param> /// <param name="stream">Stream to hash</param>
/// <returns>MD5 hash as a hex string</returns> /// <returns>MD5 hash as a hex string</returns>
@@ -321,7 +321,7 @@ public static class Utility
} }
/// <summary> /// <summary>
/// Convert the given array to a hex string. /// Convert the given array to a hex string.
/// </summary> /// </summary>
/// <param name="data">Bytes to convert.</param> /// <param name="data">Bytes to convert.</param>
/// <returns>Bytes reinterpreted as a hex number.</returns> /// <returns>Bytes reinterpreted as a hex number.</returns>
@@ -374,8 +374,8 @@ public static class Utility
} }
/// <summary> /// <summary>
/// Gets unique files in all given directories. If the file with the same name exists in multiple directories, /// Gets unique files in all given directories. If the file with the same name exists in multiple directories,
/// only the first occurrence is returned. /// only the first occurrence is returned.
/// </summary> /// </summary>
/// <param name="directories">Directories to search from.</param> /// <param name="directories">Directories to search from.</param>
/// <param name="pattern">File pattern to search.</param> /// <param name="pattern">File pattern to search.</param>
+2 -3
View File
@@ -24,9 +24,8 @@ public abstract class BasePlugin
public virtual bool Unload() => false; public virtual bool Unload() => false;
/// <summary> /// <summary>
/// Add a Component (e.g. MonoBehaviour) into Unity scene. /// Add a Component (e.g. MonoBehaviour) into Unity scene.
/// /// Automatically registers the type with Il2Cpp Type system if it isn't already.
/// Automatically registers the type with Il2Cpp Type system if it isn't already.
/// </summary> /// </summary>
/// <typeparam name="T">Type of the component to add.</typeparam> /// <typeparam name="T">Type of the component to add.</typeparam>
public T AddComponent<T>() where T : Il2CppObjectBase => IL2CPPChainloader.AddUnityComponent<T>(); public T AddComponent<T>() where T : Il2CppObjectBase => IL2CPPChainloader.AddUnityComponent<T>();
+2 -1
View File
@@ -143,7 +143,8 @@ public class FastNativeDetour : IDetour
var trampolineAlloc = PageAllocator.Instance.Allocate(OriginalFunctionPtr); var trampolineAlloc = PageAllocator.Instance.Allocate(OriginalFunctionPtr);
logger.Log(LogLevel.Debug, $"Original: {OriginalFunctionPtr.ToInt64():X}, Trampoline: {(long) trampolineAlloc:X}, diff: {Math.Abs(OriginalFunctionPtr.ToInt64() - trampolineAlloc):X}; is within +-1GB range: {PageAllocator.IsInRelJmpRange(OriginalFunctionPtr, trampolineAlloc)}"); logger.Log(LogLevel.Debug,
$"Original: {OriginalFunctionPtr.ToInt64():X}, Trampoline: {trampolineAlloc:X}, diff: {Math.Abs(OriginalFunctionPtr.ToInt64() - trampolineAlloc):X}; is within +-1GB range: {PageAllocator.IsInRelJmpRange(OriginalFunctionPtr, trampolineAlloc)}");
DetourHelper.Native.MakeWritable(trampolineAlloc, PageAllocator.PAGE_SIZE); DetourHelper.Native.MakeWritable(trampolineAlloc, PageAllocator.PAGE_SIZE);
+6 -7
View File
@@ -42,17 +42,15 @@ public class IL2CPPChainloader : BaseChainloader<BasePlugin>
public static IL2CPPChainloader Instance { get; set; } public static IL2CPPChainloader Instance { get; set; }
/// <summary> /// <summary>
/// Register and add a Unity Component (for example MonoBehaviour) into BepInEx global manager. /// Register and add a Unity Component (for example MonoBehaviour) into BepInEx global manager.
/// /// Automatically registers the type with Il2Cpp type system if it isn't initialised already.
/// Automatically registers the type with Il2Cpp type system if it isn't initialised already.
/// </summary> /// </summary>
/// <typeparam name="T">Type of the component to add.</typeparam> /// <typeparam name="T">Type of the component to add.</typeparam>
public static T AddUnityComponent<T>() where T : Il2CppObjectBase => AddUnityComponent(typeof(T)).Cast<T>(); public static T AddUnityComponent<T>() where T : Il2CppObjectBase => AddUnityComponent(typeof(T)).Cast<T>();
/// <summary> /// <summary>
/// Register and add a Unity Component (for example MonoBehaviour) into BepInEx global manager. /// Register and add a Unity Component (for example MonoBehaviour) into BepInEx global manager.
/// /// Automatically registers the type with Il2Cpp type system if it isn't initialised already.
/// Automatically registers the type with Il2Cpp type system if it isn't initialised already.
/// </summary> /// </summary>
/// <param name="t">Type of the component to add</param> /// <param name="t">Type of the component to add</param>
public static Il2CppObjectBase AddUnityComponent(Type t) => Il2CppUtils.AddComponent(t); public static Il2CppObjectBase AddUnityComponent(Type t) => Il2CppUtils.AddComponent(t);
@@ -73,7 +71,8 @@ public class IL2CPPChainloader : BaseChainloader<BasePlugin>
if (gameAssemblyModule == null) if (gameAssemblyModule == null)
{ {
Logger.Log(LogLevel.Fatal, "Could not locate Il2Cpp game assembly (GameAssembly.dll) or (UserAssembly.dll). The game might be obfuscated or use a yet unsupported build of Unity."); Logger.Log(LogLevel.Fatal,
"Could not locate Il2Cpp game assembly (GameAssembly.dll) or (UserAssembly.dll). The game might be obfuscated or use a yet unsupported build of Unity.");
return; return;
} }
@@ -6,8 +6,6 @@ namespace BepInEx.IL2CPP.Logging;
public class IL2CPPUnityLogSource : ILogSource public class IL2CPPUnityLogSource : ILogSource
{ {
private delegate IntPtr SetLogCallbackDefinedDelegate(bool defined);
public IL2CPPUnityLogSource() public IL2CPPUnityLogSource()
{ {
Application.s_LogCallbackHandler = new Action<string, string, LogType>(UnityLogCallback); Application.s_LogCallbackHandler = new Action<string, string, LogType>(UnityLogCallback);
@@ -36,4 +34,6 @@ public class IL2CPPUnityLogSource : ILogSource
}; };
LogEvent?.Invoke(this, new LogEventArgs(logLine, level, this)); LogEvent?.Invoke(this, new LogEventArgs(logLine, level, this));
} }
private delegate IntPtr SetLogCallbackDefinedDelegate(bool defined);
} }
+6 -6
View File
@@ -51,9 +51,9 @@ public static class Preloader
ChainloaderLogHelper.PrintLogInfo(Log); ChainloaderLogHelper.PrintLogInfo(Log);
Log.Log(LogLevel.Debug,$"Game executable path: {Paths.ExecutablePath}"); Log.Log(LogLevel.Debug, $"Game executable path: {Paths.ExecutablePath}");
Log.Log(LogLevel.Debug,$"Unhollowed assembly directory: {IL2CPPUnhollowedPath}"); Log.Log(LogLevel.Debug, $"Unhollowed assembly directory: {IL2CPPUnhollowedPath}");
Log.Log(LogLevel.Debug,$"BepInEx root path: {Paths.BepInExRootPath}"); Log.Log(LogLevel.Debug, $"BepInEx root path: {Paths.BepInExRootPath}");
UnhollowerLog = Logger.CreateLogSource("Unhollower"); UnhollowerLog = Logger.CreateLogSource("Unhollower");
LogSupport.InfoHandler += UnhollowerLog.LogInfo; LogSupport.InfoHandler += UnhollowerLog.LogInfo;
@@ -100,11 +100,11 @@ public static class Preloader
private static void InitializeUnityVersion() private static void InitializeUnityVersion()
{ {
if (TryInitializeUnityVersion(ConfigUnityVersion.Value)) if (TryInitializeUnityVersion(ConfigUnityVersion.Value))
Log.LogWarning($"Unity version obtained from the config."); Log.LogWarning("Unity version obtained from the config.");
else if (TryInitializeUnityVersion(Process.GetCurrentProcess().MainModule.FileVersionInfo.FileVersion)) else if (TryInitializeUnityVersion(Process.GetCurrentProcess().MainModule.FileVersionInfo.FileVersion))
Log.LogDebug($"Unity version obtained from main application module."); Log.LogDebug("Unity version obtained from main application module.");
else else
Log.LogError($"Running under default Unity version. UnityVersionHandler is not initialized."); Log.LogError("Running under default Unity version. UnityVersionHandler is not initialized.");
} }
private static bool TryInitializeUnityVersion(string version) private static bool TryInitializeUnityVersion(string version)
+5 -3
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Net.Http; using System.Net.Http;
@@ -53,7 +54,7 @@ internal static class ProxyAssemblyGenerator
false, false,
"If enabled, BepInEx will save dummy assemblies generated by an il2cpp dumper into BepInEx/dummy."); "If enabled, BepInEx will save dummy assemblies generated by an il2cpp dumper into BepInEx/dummy.");
private static ManualLogSource Il2cppDumperLogger = null; private static ManualLogSource Il2cppDumperLogger;
public static string GameAssemblyPath => Path.Combine(Paths.GameRootPath, "GameAssembly.dll"); public static string GameAssemblyPath => Path.Combine(Paths.GameRootPath, "GameAssembly.dll");
@@ -109,7 +110,8 @@ internal static class ProxyAssemblyGenerator
{ {
var hash = ComputeHash(); var hash = ComputeHash();
Preloader.Log Preloader.Log
.Log(LogLevel.Warning, $"Unhollowed assemblies are possibly out of date. To disable this message, create file {HashPath} with the following contents: {hash}"); .Log(LogLevel.Warning,
$"Unhollowed assemblies are possibly out of date. To disable this message, create file {HashPath} with the following contents: {hash}");
return false; return false;
} }
@@ -254,7 +256,7 @@ internal static class ProxyAssemblyGenerator
List<AssemblyDefinition> sourceAssemblies; List<AssemblyDefinition> sourceAssemblies;
var stopwatch = new System.Diagnostics.Stopwatch(); var stopwatch = new Stopwatch();
stopwatch.Start(); stopwatch.Start();
if (dumperType == IL2CPPDumperType.Il2CppDumper) if (dumperType == IL2CPPDumperType.Il2CppDumper)
@@ -5,7 +5,7 @@ namespace BepInEx.IL2CPP.Utils.Collections;
public class ManagedIl2CppEnumerable : IEnumerable public class ManagedIl2CppEnumerable : IEnumerable
{ {
private Il2CppSystem.Collections.IEnumerable enumerable; private readonly Il2CppSystem.Collections.IEnumerable enumerable;
public ManagedIl2CppEnumerable(Il2CppSystem.Collections.IEnumerable enumerable) public ManagedIl2CppEnumerable(Il2CppSystem.Collections.IEnumerable enumerable)
{ {
+13 -11
View File
@@ -20,6 +20,15 @@ public static class NetPreloader
{ {
private static readonly ManualLogSource Log = PreloaderLogger.Log; private static readonly ManualLogSource Log = PreloaderLogger.Log;
#region Config
private static readonly ConfigEntry<string> ConfigEntrypointExecutable = ConfigFile.CoreConfig.Bind<string>(
"Preloader.Entrypoint", "Assembly",
null,
"The local filename of the .NET executable to target.");
#endregion
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SetDllDirectory(string lpPathName); private static extern bool SetDllDirectory(string lpPathName);
@@ -34,7 +43,8 @@ public static class NetPreloader
if (string.IsNullOrEmpty(ConfigEntrypointExecutable.Value)) if (string.IsNullOrEmpty(ConfigEntrypointExecutable.Value))
{ {
Log.Log(LogLevel.Fatal, $"Entry executable was not set. Please set this in your config before launching the application"); Log.Log(LogLevel.Fatal,
$"Entry executable was not set. Please set this in your config before launching the application");
Program.ReadExit(); Program.ReadExit();
return; return;
} }
@@ -76,7 +86,8 @@ public static class NetPreloader
{ {
assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath); assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);
Log.Log(LogLevel.Info, $"{assemblyPatcher.PatcherContext.PatchDefinitions.Count} patcher definition(s) loaded"); Log.Log(LogLevel.Info,
$"{assemblyPatcher.PatcherContext.PatchDefinitions.Count} patcher definition(s) loaded");
assemblyPatcher.LoadAssemblyDirectories(new[] { Paths.GameRootPath }, new[] { "dll", "exe" }); assemblyPatcher.LoadAssemblyDirectories(new[] { Paths.GameRootPath }, new[] { "dll", "exe" });
@@ -152,13 +163,4 @@ public static class NetPreloader
Log.LogFatal($"Unhandled exception: {ex}"); Log.LogFatal($"Unhandled exception: {ex}");
} }
} }
#region Config
private static readonly ConfigEntry<string> ConfigEntrypointExecutable = ConfigFile.CoreConfig.Bind<string>(
"Preloader.Entrypoint", "Assembly",
null,
"The local filename of the .NET executable to target.");
#endregion
} }
+1 -1
View File
@@ -26,7 +26,7 @@ public static class EnvVars
public static string DOORSTOP_PROCESS_PATH { get; private set; } public static string DOORSTOP_PROCESS_PATH { get; private set; }
/// <summary> /// <summary>
/// Array of paths where Mono searches DLLs from before assembly resolvers are invoked. /// Array of paths where Mono searches DLLs from before assembly resolvers are invoked.
/// </summary> /// </summary>
public static string[] DOORSTOP_DLL_SEARCH_DIRS { get; private set; } public static string[] DOORSTOP_DLL_SEARCH_DIRS { get; private set; }
@@ -23,10 +23,7 @@ public class PreloaderConsoleListener : ILogListener
public LogLevel LogLevelFilter => ConfigConsoleDisplayedLevel.Value; public LogLevel LogLevelFilter => ConfigConsoleDisplayedLevel.Value;
/// <inheritdoc /> /// <inheritdoc />
public void LogEvent(object sender, LogEventArgs eventArgs) public void LogEvent(object sender, LogEventArgs eventArgs) => LogEvents.Add(eventArgs);
{
LogEvents.Add(eventArgs);
}
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() { } public void Dispose() { }
@@ -23,7 +23,7 @@ public class AssemblyPatcher : IDisposable
private static readonly string CurrentAssemblyName = Assembly.GetExecutingAssembly().GetName().Name; private static readonly string CurrentAssemblyName = Assembly.GetExecutingAssembly().GetName().Name;
/// <summary> /// <summary>
/// The context of this assembly patcher instance that is passed to all patcher plugins. /// The context of this assembly patcher instance that is passed to all patcher plugins.
/// </summary> /// </summary>
public PatcherContext PatcherContext { get; } = new() public PatcherContext PatcherContext { get; } = new()
{ {
@@ -81,7 +81,8 @@ public class AssemblyPatcher : IDisposable
if (string.IsNullOrEmpty(metadata.GUID) || !allowedGuidRegex.IsMatch(metadata.GUID)) if (string.IsNullOrEmpty(metadata.GUID) || !allowedGuidRegex.IsMatch(metadata.GUID))
{ {
Logger.Log(LogLevel.Warning, $"Skipping type [{type.FullName}] because its GUID [{metadata.GUID}] is of an illegal format"); Logger.Log(LogLevel.Warning,
$"Skipping type [{type.FullName}] because its GUID [{metadata.GUID}] is of an illegal format");
return null; return null;
} }
@@ -180,7 +181,8 @@ public class AssemblyPatcher : IDisposable
) )
{ {
Logger Logger
.Log(LogLevel.Warning, $"Skipping method [{method.FullDescription()}] as it is not a valid patcher method"); .Log(LogLevel.Warning,
$"Skipping method [{method.FullDescription()}] as it is not a valid patcher method");
continue; continue;
} }
@@ -211,7 +213,8 @@ public class AssemblyPatcher : IDisposable
/// <summary> /// <summary>
/// Adds all .dll assemblies in given directories to be patched and loaded by this patcher instance. Non-managed assemblies /// Adds all .dll assemblies in given directories to be patched and loaded by this patcher instance. Non-managed
/// assemblies
/// are skipped. /// are skipped.
/// </summary> /// </summary>
/// <param name="directories">The directories to search.</param> /// <param name="directories">The directories to search.</param>
@@ -219,7 +222,8 @@ public class AssemblyPatcher : IDisposable
LoadAssemblyDirectories(directories, new[] { "dll" }); LoadAssemblyDirectories(directories, new[] { "dll" });
/// <summary> /// <summary>
/// Adds all assemblies in given directories to be patched and loaded by this patcher instance. Non-managed assemblies are /// Adds all assemblies in given directories to be patched and loaded by this patcher instance. Non-managed assemblies
/// are
/// skipped. /// skipped.
/// </summary> /// </summary>
/// <param name="directories">The directory to search.</param> /// <param name="directories">The directory to search.</param>
@@ -386,7 +390,8 @@ public class AssemblyPatcher : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Log(LogLevel.Error, $"Failed to run [{patchDefinition.FullName}] when patching [{assembly.Name.Name}]. This assembly will not be patched. Error: {e}"); Logger.Log(LogLevel.Error,
$"Failed to run [{patchDefinition.FullName}] when patching [{assembly.Name.Name}]. This assembly will not be patched. Error: {e}");
patchedAssemblies.Remove(targetDll); patchedAssemblies.Remove(targetDll);
invalidAssemblies.Add(targetDll); invalidAssemblies.Add(targetDll);
return false; return false;
@@ -416,14 +421,14 @@ public class AssemblyPatcher : IDisposable
if (earlyLoadAssemblies.Count != 0) if (earlyLoadAssemblies.Count != 0)
Logger.Log(LogLevel.Warning, new StringBuilder() Logger.Log(LogLevel.Warning, new StringBuilder()
.AppendLine("The following assemblies have been loaded too early and will not be patched by preloader:") .AppendLine("The following assemblies have been loaded too early and will not be patched by preloader:")
.AppendLine(string.Join(Environment.NewLine, .AppendLine(string.Join(Environment.NewLine,
earlyLoadAssemblies earlyLoadAssemblies
.Select(kv => .Select(kv =>
$"* [{kv.Key}] (first loaded by [{kv.Value}])") $"* [{kv.Key}] (first loaded by [{kv.Value}])")
.ToArray())) .ToArray()))
.AppendLine("Expect unexpected behavior and issues with plugins and patchers not being loaded.") .AppendLine("Expect unexpected behavior and issues with plugins and patchers not being loaded.")
.ToString()); .ToString());
var dumpedAssemblyPaths = new Dictionary<string, string>(); var dumpedAssemblyPaths = new Dictionary<string, string>();
// Finally, load patched assemblies into memory // Finally, load patched assemblies into memory
@@ -457,7 +462,8 @@ public class AssemblyPatcher : IDisposable
if (ConfigBreakBeforeLoadAssemblies.Value) if (ConfigBreakBeforeLoadAssemblies.Value)
{ {
Logger.Log(LogLevel.Info, $"BepInEx is about load the following assemblies:\n{string.Join("\n", patchedAssemblies.ToArray())}"); Logger.Log(LogLevel.Info,
$"BepInEx is about load the following assemblies:\n{string.Join("\n", patchedAssemblies.ToArray())}");
Logger.Log(LogLevel.Info, $"The assemblies were dumped into {PatcherContext.DumpedAssembliesPath}"); Logger.Log(LogLevel.Info, $"The assemblies were dumped into {PatcherContext.DumpedAssembliesPath}");
Logger.Log(LogLevel.Info, "Load any assemblies into the debugger, set breakpoints and continue execution."); Logger.Log(LogLevel.Info, "Load any assemblies into the debugger, set breakpoints and continue execution.");
Debugger.Break(); Debugger.Break();
+11 -8
View File
@@ -80,35 +80,38 @@ public class PatcherPluginInfoAttribute : Attribute
} }
/// <summary> /// <summary>
/// Defines an assembly that a patch method will target. /// Defines an assembly that a patch method will target.
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Method)] [AttributeUsage(AttributeTargets.Method)]
public class TargetAssemblyAttribute : Attribute public class TargetAssemblyAttribute : Attribute
{ {
/// <summary> /// <summary>
/// Marker used to indicate all possible assemblies to be targeted by a patch method. /// Marker used to indicate all possible assemblies to be targeted by a patch method.
/// </summary> /// </summary>
public const string AllAssemblies = "_all"; public const string AllAssemblies = "_all";
/// <param name="targetAssembly">The short filename of the assembly. Use <see cref="AllAssemblies"/> to mark all possible assemblies as targets.</param> /// <param name="targetAssembly">
/// The short filename of the assembly. Use <see cref="AllAssemblies" /> to mark all possible
/// assemblies as targets.
/// </param>
public TargetAssemblyAttribute(string targetAssembly) public TargetAssemblyAttribute(string targetAssembly)
{ {
TargetAssembly = targetAssembly; TargetAssembly = targetAssembly;
} }
/// <summary> /// <summary>
/// The short filename of the assembly to target. /// The short filename of the assembly to target.
/// </summary> /// </summary>
public string TargetAssembly { get; } public string TargetAssembly { get; }
} }
/// <summary> /// <summary>
/// Defines a type that a patch method will target. /// Defines a type that a patch method will target.
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Method)] [AttributeUsage(AttributeTargets.Method)]
public class TargetTypeAttribute : Attribute public class TargetTypeAttribute : Attribute
{ {
/// <param name="targetAssembly">The short filename of the assembly of which <paramref name="targetType"/> belongs to.</param> /// <param name="targetAssembly">The short filename of the assembly of which <paramref name="targetType" /> belongs to.</param>
/// <param name="targetType">The full name of the type to target for patching.</param> /// <param name="targetType">The full name of the type to target for patching.</param>
public TargetTypeAttribute(string targetAssembly, string targetType) public TargetTypeAttribute(string targetAssembly, string targetType)
{ {
@@ -117,12 +120,12 @@ public class TargetTypeAttribute : Attribute
} }
/// <summary> /// <summary>
/// The short filename of the assembly to target. /// The short filename of the assembly to target.
/// </summary> /// </summary>
public string TargetAssembly { get; } public string TargetAssembly { get; }
/// <summary> /// <summary>
/// The full name of the type to target for patching. /// The full name of the type to target for patching.
/// </summary> /// </summary>
public string TargetType { get; } public string TargetType { get; }
} }
+21 -20
View File
@@ -8,26 +8,6 @@ namespace BepInEx.Preloader.Core.Patching;
/// </summary> /// </summary>
public abstract class BasePatcher public abstract class BasePatcher
{ {
/// <summary>
/// A <see cref="ILogSource"/> instance created for use by this patcher plugin.
/// </summary>
public ManualLogSource Log { get; }
/// <summary>
/// A configuration file binding created with the <see cref="PatcherPluginInfoAttribute.GUID"/> of this plugin as the filename.
/// </summary>
public ConfigFile Config { get; }
/// <summary>
/// Metadata associated with this patcher plugin.
/// </summary>
public PatcherPluginInfoAttribute Info { get; }
/// <summary>
/// The context of the <see cref="AssemblyPatcher"/> this BasePatcher is associated with.
/// </summary>
public PatcherContext Context { get; set; }
protected BasePatcher() protected BasePatcher()
{ {
Info = PatcherPluginInfoAttribute.FromType(GetType()); Info = PatcherPluginInfoAttribute.FromType(GetType());
@@ -38,6 +18,27 @@ public abstract class BasePatcher
new BepInPlugin(Info.GUID, Info.Name, Info.Version.ToString())); new BepInPlugin(Info.GUID, Info.Name, Info.Version.ToString()));
} }
/// <summary>
/// A <see cref="ILogSource" /> instance created for use by this patcher plugin.
/// </summary>
public ManualLogSource Log { get; }
/// <summary>
/// A configuration file binding created with the <see cref="PatcherPluginInfoAttribute.GUID" /> of this plugin as the
/// filename.
/// </summary>
public ConfigFile Config { get; }
/// <summary>
/// Metadata associated with this patcher plugin.
/// </summary>
public PatcherPluginInfoAttribute Info { get; }
/// <summary>
/// The context of the <see cref="AssemblyPatcher" /> this BasePatcher is associated with.
/// </summary>
public PatcherContext Context { get; set; }
/// <summary> /// <summary>
/// Executed before any patches from any plugin are applied. /// Executed before any patches from any plugin are applied.
/// </summary> /// </summary>
@@ -5,7 +5,7 @@ using Mono.Cecil;
namespace BepInEx.Preloader.Core.Patching; namespace BepInEx.Preloader.Core.Patching;
/// <summary> /// <summary>
/// A definition of an individual patch for use by <see cref="AssemblyPatcher"/>. /// A definition of an individual patch for use by <see cref="AssemblyPatcher" />.
/// </summary> /// </summary>
public class PatchDefinition public class PatchDefinition
{ {
@@ -31,20 +31,20 @@ public class PatchDefinition
/// <summary> /// <summary>
/// The assembly / assemblies this patch will target, if there any. /// The assembly / assemblies this patch will target, if there any.
/// </summary> /// </summary>
public TargetAssemblyAttribute TargetAssembly { get; } = null; public TargetAssemblyAttribute TargetAssembly { get; }
/// <summary> /// <summary>
/// The type / types this patch will target, if there are any. /// The type / types this patch will target, if there are any.
/// </summary> /// </summary>
public TargetTypeAttribute TargetType { get; } = null; public TargetTypeAttribute TargetType { get; }
/// <summary> /// <summary>
/// The instance of the <see cref="BasePatcher"/> this <see cref="PatchDefinition"/> originates from. /// The instance of the <see cref="BasePatcher" /> this <see cref="PatchDefinition" /> originates from.
/// </summary> /// </summary>
public BasePatcher Instance { get; } public BasePatcher Instance { get; }
/// <summary> /// <summary>
/// The method that will perform the patching logic defined by this <see cref="PatchDefinition"/> instance. /// The method that will perform the patching logic defined by this <see cref="PatchDefinition" /> instance.
/// </summary> /// </summary>
public MethodInfo MethodInfo { get; } public MethodInfo MethodInfo { get; }
@@ -55,7 +55,7 @@ public class PatchDefinition
} }
/// <summary> /// <summary>
/// Context provided to patcher plugins from the associated patcher engine. /// Context provided to patcher plugins from the associated patcher engine.
/// </summary> /// </summary>
public class PatcherContext public class PatcherContext
{ {
@@ -85,7 +85,8 @@ public class PatcherContext
public List<BasePatcher> PatcherPlugins { get; } = new(); public List<BasePatcher> PatcherPlugins { get; } = new();
/// <summary> /// <summary>
/// A list of individual patches that <see cref="AssemblyPatcher"/> will execute, generated by parsing <see cref="PatcherPlugins"/>. /// A list of individual patches that <see cref="AssemblyPatcher" /> will execute, generated by parsing
/// <see cref="PatcherPlugins" />.
/// </summary> /// </summary>
public List<PatchDefinition> PatchDefinitions { get; } = new(); public List<PatchDefinition> PatchDefinitions { get; } = new();
+20 -19
View File
@@ -14,7 +14,24 @@ namespace BepInEx.Preloader.Unity;
[PatcherPluginInfo("io.bepinex.entrypointpatcher", "BepInEx Entrypoint", "1.0")] [PatcherPluginInfo("io.bepinex.entrypointpatcher", "BepInEx Entrypoint", "1.0")]
internal class EntrypointPatcher : BasePatcher internal class EntrypointPatcher : BasePatcher
{ {
private bool HasLoaded { get; set; } = false; private static readonly ConfigEntry<string> ConfigEntrypointAssembly = ConfigFile.CoreConfig.Bind(
"Preloader.Entrypoint", "Assembly",
UnityPreloader.IsPostUnity2017
? "UnityEngine.CoreModule.dll"
: "UnityEngine.dll",
"The local filename of the assembly to target.");
private static readonly ConfigEntry<string> ConfigEntrypointType = ConfigFile.CoreConfig.Bind(
"Preloader.Entrypoint", "Type",
"Application",
"The name of the type in the entrypoint assembly to search for the entrypoint method.");
private static readonly ConfigEntry<string> ConfigEntrypointMethod = ConfigFile.CoreConfig.Bind(
"Preloader.Entrypoint", "Method",
".cctor",
"The name of the method in the specified entrypoint assembly and type to hook and load Chainloader from.");
private bool HasLoaded { get; set; }
[TargetAssembly(TargetAssemblyAttribute.AllAssemblies)] [TargetAssembly(TargetAssemblyAttribute.AllAssemblies)]
public bool PatchEntrypoint(ref AssemblyDefinition assembly, string filename) public bool PatchEntrypoint(ref AssemblyDefinition assembly, string filename)
@@ -110,23 +127,7 @@ internal class EntrypointPatcher : BasePatcher
public override void Finalizer() public override void Finalizer()
{ {
if (!HasLoaded) if (!HasLoaded)
Log.Log(LogLevel.Fatal, $"Failed to patch BepInEx chainloader into assembly '{ConfigEntrypointAssembly.Value}', either due to error or not being able to find it. Is it spelled correctly?"); Log.Log(LogLevel.Fatal,
$"Failed to patch BepInEx chainloader into assembly '{ConfigEntrypointAssembly.Value}', either due to error or not being able to find it. Is it spelled correctly?");
} }
private static readonly ConfigEntry<string> ConfigEntrypointAssembly = ConfigFile.CoreConfig.Bind(
"Preloader.Entrypoint", "Assembly",
UnityPreloader.IsPostUnity2017
? "UnityEngine.CoreModule.dll"
: "UnityEngine.dll",
"The local filename of the assembly to target.");
private static readonly ConfigEntry<string> ConfigEntrypointType = ConfigFile.CoreConfig.Bind(
"Preloader.Entrypoint", "Type",
"Application",
"The name of the type in the entrypoint assembly to search for the entrypoint method.");
private static readonly ConfigEntry<string> ConfigEntrypointMethod = ConfigFile.CoreConfig.Bind(
"Preloader.Entrypoint", "Method",
".cctor",
"The name of the method in the specified entrypoint assembly and type to hook and load Chainloader from.");
} }
+10 -7
View File
@@ -53,15 +53,16 @@ internal static class UnityPreloader
ChainloaderLogHelper.PrintLogInfo(Log); ChainloaderLogHelper.PrintLogInfo(Log);
Log.Log(LogLevel.Info, $"Running under Unity v{GetUnityVersion()}"); Log.Log(LogLevel.Info, $"Running under Unity v{GetUnityVersion()}");
Log.Log(LogLevel.Info,$"CLR runtime version: {Environment.Version}"); Log.Log(LogLevel.Info, $"CLR runtime version: {Environment.Version}");
Log.Log(LogLevel.Info,$"Supports SRE: {Utility.CLRSupportsDynamicAssemblies}"); Log.Log(LogLevel.Info, $"Supports SRE: {Utility.CLRSupportsDynamicAssemblies}");
Log.Log(LogLevel.Debug, $"Game executable path: {Paths.ExecutablePath}"); Log.Log(LogLevel.Debug, $"Game executable path: {Paths.ExecutablePath}");
Log.Log(LogLevel.Debug,$"Unity Managed directory: {Paths.ManagedPath}"); Log.Log(LogLevel.Debug, $"Unity Managed directory: {Paths.ManagedPath}");
Log.Log(LogLevel.Debug,$"BepInEx root path: {Paths.BepInExRootPath}"); Log.Log(LogLevel.Debug, $"BepInEx root path: {Paths.BepInExRootPath}");
if (runtimePatchException != null) if (runtimePatchException != null)
Log.Log(LogLevel.Warning, $"Failed to apply runtime patches for Mono. See more info in the output log. Error message: {runtimePatchException.Message}"); Log.Log(LogLevel.Warning,
$"Failed to apply runtime patches for Mono. See more info in the output log. Error message: {runtimePatchException.Message}");
Log.Log(LogLevel.Message, "Preloader started"); Log.Log(LogLevel.Message, "Preloader started");
@@ -72,11 +73,13 @@ internal static class UnityPreloader
assemblyPatcher.AddPatchersFromDirectory(Paths.BepInExAssemblyDirectory); assemblyPatcher.AddPatchersFromDirectory(Paths.BepInExAssemblyDirectory);
assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath); assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);
Log.Log(LogLevel.Info, $"{assemblyPatcher.PatcherContext.PatcherPlugins.Count} patcher plugin{(assemblyPatcher.PatcherContext.PatcherPlugins.Count == 1 ? "" : "s")} loaded"); Log.Log(LogLevel.Info,
$"{assemblyPatcher.PatcherContext.PatcherPlugins.Count} patcher plugin{(assemblyPatcher.PatcherContext.PatcherPlugins.Count == 1 ? "" : "s")} loaded");
assemblyPatcher.LoadAssemblyDirectories(Paths.DllSearchPaths); assemblyPatcher.LoadAssemblyDirectories(Paths.DllSearchPaths);
Log.Log(LogLevel.Info, $"{assemblyPatcher.PatcherContext.AvailableAssemblies.Count} assemblies discovered"); Log.Log(LogLevel.Info,
$"{assemblyPatcher.PatcherContext.AvailableAssemblies.Count} assemblies discovered");
assemblyPatcher.PatchAndLoad(); assemblyPatcher.PatchAndLoad();
} }
@@ -54,7 +54,7 @@ public struct KeyboardShortcut
/// <param name="mainKey">Main key to press</param> /// <param name="mainKey">Main key to press</param>
/// <param name="modifiers">Keys that should be held down before main key is registered</param> /// <param name="modifiers">Keys that should be held down before main key is registered</param>
public KeyboardShortcut(KeyCode mainKey, params KeyCode[] modifiers) : this(new[] { mainKey }.Concat(modifiers) public KeyboardShortcut(KeyCode mainKey, params KeyCode[] modifiers) : this(new[] { mainKey }.Concat(modifiers)
.ToArray()) .ToArray())
{ {
if (mainKey == KeyCode.None && modifiers.Any()) if (mainKey == KeyCode.None && modifiers.Any())
throw new throw new
+5 -5
View File
@@ -16,17 +16,17 @@ namespace BepInEx.Unity.Logging
{ {
internal static readonly Action<string> WriteStringToUnityLog; internal static readonly Action<string> WriteStringToUnityLog;
protected static readonly ConfigEntry<LogLevel> ConfigUnityLogLevel = ConfigFile.CoreConfig.Bind(
"Logging.Unity", "LogLevels",
LogLevel.Fatal | LogLevel.Error | LogLevel.Warning | LogLevel.Message | LogLevel.Info,
"What log levels to log to Unity's output log.");
private readonly ConfigEntry<bool> LogConsoleToUnity = ConfigFile.CoreConfig.Bind("Logging", private readonly ConfigEntry<bool> LogConsoleToUnity = ConfigFile.CoreConfig.Bind("Logging",
"LogConsoleToUnityLog", false, "LogConsoleToUnityLog", false,
new StringBuilder() new StringBuilder()
.AppendLine("If enabled, writes Standard Output messages to Unity log") .AppendLine("If enabled, writes Standard Output messages to Unity log")
.AppendLine("NOTE: By default, Unity does so automatically. Only use this option if no console messages are visible in Unity log") .AppendLine("NOTE: By default, Unity does so automatically. Only use this option if no console messages are visible in Unity log")
.ToString()); .ToString());
protected static readonly ConfigEntry<LogLevel> ConfigUnityLogLevel = ConfigFile.CoreConfig.Bind(
"Logging.Unity", "LogLevels",
LogLevel.Fatal | LogLevel.Error | LogLevel.Warning | LogLevel.Message | LogLevel.Info,
"What log levels to log to Unity's output log.");
static UnityLogListener() static UnityLogListener()
{ {