mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
Reformat project; apply code style
This commit is contained in:
1 parent
81141fcfc4
commit
4bb48c502e
30 files changed
+213
-172
No files matched your search
@@ -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}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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.");
|
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user