diff --git a/.github/workflows/test-full.yml b/.github/workflows/test-full.yml
index 4a576d9a..9dbc7dce 100644
--- a/.github/workflows/test-full.yml
+++ b/.github/workflows/test-full.yml
@@ -71,7 +71,7 @@ jobs:
shell: pwsh
- name: ReportGenerator
- uses: danielpalme/ReportGenerator-GitHub-Action@5.1.22
+ uses: danielpalme/ReportGenerator-GitHub-Action@5.1.23
with:
reports: '*.xml'
targetdir: 'coveragereport'
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 71dcfe18..866cbd41 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -77,7 +77,7 @@ jobs:
shell: pwsh
- name: ReportGenerator
- uses: danielpalme/ReportGenerator-GitHub-Action@5.1.22
+ uses: danielpalme/ReportGenerator-GitHub-Action@5.1.23
with:
reports: 'coverage_butterlib_stable_debug.xml;coverage_butterlib_stable_release.xml;coverage_butterlib_impl_stable_debug.xml;coverage_butterlib_impl_stable_release.xml;coverage_butterlib_impl_beta_debug.xml;coverage_butterlib_impl_beta_release.xml;'
targetdir: 'coveragereport'
diff --git a/build/common.props b/build/common.props
index af1fb72c..59859f38 100644
--- a/build/common.props
+++ b/build/common.props
@@ -4,7 +4,7 @@
- 2.8.3
+ 2.8.4
2.2.2
3.2.0.77
@@ -15,7 +15,7 @@
2.0.0
1.1.0.102
- 3.0.0.136
+ 3.0.0.137
5.0.209
diff --git a/changelog.txt b/changelog.txt
index 958226c9..5d7122f0 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,4 +1,9 @@
---------------------------------------------------------------------------------------------------
+Version: 2.8.4
+Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0,v1.1.1,v1.1.2,v1.1.3,v1.1.4,v1.1.5,v1.2.0
+* ButterLib is not able to disable v1.2.0 Watchdog, BLSE is required
+* Added integration with BLSE's better exception intercepter
+---------------------------------------------------------------------------------------------------
Version: 2.8.3
Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0,v1.1.1,v1.1.2,v1.1.3,v1.1.4,v1.1.5,v1.2.0
* The UseVanillaCrashHandler setting wasn't set correctly
diff --git a/src/Bannerlord.ButterLib.Implementation/DistanceMatrix/DistanceMatrixSubSystem.cs b/src/Bannerlord.ButterLib.Implementation/DistanceMatrix/DistanceMatrixSubSystem.cs
index a6b7b823..ded711cc 100644
--- a/src/Bannerlord.ButterLib.Implementation/DistanceMatrix/DistanceMatrixSubSystem.cs
+++ b/src/Bannerlord.ButterLib.Implementation/DistanceMatrix/DistanceMatrixSubSystem.cs
@@ -9,7 +9,8 @@ internal class DistanceMatrixSubSystem : ISubSystem
public static DistanceMatrixSubSystem? Instance { get; private set; }
public string Id => "Distance Matrix";
- public string Description => "Mod Developer feature! Provides helpers to calculate distance between objects on map.";
+ public string Name => "{=Ox6uK8fZWs}Distance Matrix";
+ public string Description => "{=WQ4r2n0mYj}Mod Developer feature! Provides helpers to calculate distance between objects on map.";
public bool IsEnabled { get; private set; } = false;
public bool CanBeDisabled => true;
public bool CanBeSwitchedAtRuntime => false;
diff --git a/src/Bannerlord.ButterLib.Implementation/HotKeys/HotKeySubSystem.cs b/src/Bannerlord.ButterLib.Implementation/HotKeys/HotKeySubSystem.cs
index 841b42ec..2cd0cada 100644
--- a/src/Bannerlord.ButterLib.Implementation/HotKeys/HotKeySubSystem.cs
+++ b/src/Bannerlord.ButterLib.Implementation/HotKeys/HotKeySubSystem.cs
@@ -18,8 +18,9 @@ internal sealed class HotKeySubSystem : ISubSystem
public static HotKeySubSystem? Instance { get; private set; }
public string Id => "Hot Keys";
+ public string Name => "{=jvV6QDc7AJ}Hot Keys";
public bool IsEnabled { get; private set; }
- public string Description => "Mod Developer feature! Provides a better way for mods to create hotkeys";
+ public string Description => "{=wNNYwgUeus}Mod Developer feature! Provides a better way for mods to create hotkeys";
public bool CanBeDisabled => true;
public bool CanBeSwitchedAtRuntime => false;
diff --git a/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/MBSubModuleBaseExSubSystem.cs b/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/MBSubModuleBaseExSubSystem.cs
index 7047c4b6..748c78a1 100644
--- a/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/MBSubModuleBaseExSubSystem.cs
+++ b/src/Bannerlord.ButterLib.Implementation/MBSubModuleBaseExtended/MBSubModuleBaseExSubSystem.cs
@@ -15,7 +15,8 @@ internal class MBSubModuleBaseExSubSystem : ISubSystem
{
public static MBSubModuleBaseExSubSystem? Instance { get; private set; }
public string Id => "MBSubModuleBase extended";
- public string Description => "Mod Developer feature! Introduces a MBSubModuleBase-derived abstract class, that provides new SubModule events.";
+ public string Name => "{=JGylAT3SrB}MBSubModuleBase Extended";
+ public string Description => "{=XfveBQYVWH}Mod Developer feature! Introduces a MBSubModuleBase-derived abstract class, that provides new SubModule events.";
public bool IsEnabled { get; private set; }
public bool CanBeDisabled => true;
public bool CanBeSwitchedAtRuntime => false;
diff --git a/src/Bannerlord.ButterLib.Implementation/ObjectSystem/ObjectSystemSubSystem.cs b/src/Bannerlord.ButterLib.Implementation/ObjectSystem/ObjectSystemSubSystem.cs
index 79e71d3a..45185174 100644
--- a/src/Bannerlord.ButterLib.Implementation/ObjectSystem/ObjectSystemSubSystem.cs
+++ b/src/Bannerlord.ButterLib.Implementation/ObjectSystem/ObjectSystemSubSystem.cs
@@ -10,7 +10,8 @@ internal class ObjectSystemSubSystem : ISubSystem
public static ObjectSystemSubSystem? Instance { get; private set; }
public string Id => "Object System";
- public string Description => "Mod Developer feature!";
+ public string Name => "{=IA0mVgHJgo}Object System";
+ public string Description => "{=mFZTv1nwOx}Mod Developer feature!";
public bool IsEnabled { get; private set; }
public bool CanBeDisabled => true;
public bool CanBeSwitchedAtRuntime => false;
diff --git a/src/Bannerlord.ButterLib.Implementation/SaveSystem/SaveSystemSubSystem.cs b/src/Bannerlord.ButterLib.Implementation/SaveSystem/SaveSystemSubSystem.cs
index 5eff2df2..ac24ca40 100644
--- a/src/Bannerlord.ButterLib.Implementation/SaveSystem/SaveSystemSubSystem.cs
+++ b/src/Bannerlord.ButterLib.Implementation/SaveSystem/SaveSystemSubSystem.cs
@@ -10,10 +10,11 @@ internal class SaveSystemSubSystem : ISubSystem
public static SaveSystemSubSystem? Instance { get; private set; }
public string Id => "Save System";
- public string Description => @"Extends and fixes the game's save system:
-* Fixes possible collision with save names;
-* Fixes save corruption & crashes when duplicate types are defined;
-* Adds support for saving many more container types;
+ public string Name => "{=66A5N9278w}Save System";
+ public string Description => @"{=9ybOxGpWb5}Extends and fixes the game's save system:{NL}
+* Fixes possible collision with save names;{NL}
+* Fixes save corruption & crashes when duplicate types are defined;{NL}
+* Adds support for saving many more container types;{NL}
This might alter the save file, disabling the feature might render the save file unloadable!";
public bool IsEnabled { get; private set; }
public bool CanBeDisabled => true;
diff --git a/src/Bannerlord.ButterLib.Implementation/_Module/ModuleData/Languages/EN/sta_strings.xml b/src/Bannerlord.ButterLib.Implementation/_Module/ModuleData/Languages/EN/sta_strings.xml
index 701703f1..f2f7e691 100644
--- a/src/Bannerlord.ButterLib.Implementation/_Module/ModuleData/Languages/EN/sta_strings.xml
+++ b/src/Bannerlord.ButterLib.Implementation/_Module/ModuleData/Languages/EN/sta_strings.xml
@@ -23,5 +23,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/CrashUploader/CrashUploaderSubSystem.cs b/src/Bannerlord.ButterLib/CrashUploader/CrashUploaderSubSystem.cs
index 26fec625..d942ad9c 100644
--- a/src/Bannerlord.ButterLib/CrashUploader/CrashUploaderSubSystem.cs
+++ b/src/Bannerlord.ButterLib/CrashUploader/CrashUploaderSubSystem.cs
@@ -7,7 +7,8 @@ internal sealed class CrashUploaderSubSystem : ISubSystem
public static CrashUploaderSubSystem? Instance { get; private set; }
public string Id => "CrashUploader";
- public string Description => "Uploads the crash reports to BUTR for an easy file hosting.";
+ public string Name => "{=UsLlrwMTjJ}Crash Uploader";
+ public string Description => "{=hjeoN9NwZm}Uploads the crash reports to BUTR for an easy file hosting.";
public bool IsEnabled { get; private set; }
public bool CanBeDisabled => true;
public bool CanBeSwitchedAtRuntime => true;
diff --git a/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleSubSystem.cs b/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleSubSystem.cs
index eb6d2b08..2acc88f6 100644
--- a/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleSubSystem.cs
+++ b/src/Bannerlord.ButterLib/DelayedSubModule/DelayedSubModuleSubSystem.cs
@@ -5,7 +5,8 @@ namespace Bannerlord.ButterLib.DelayedSubModule
internal class DelayedSubModuleSubSystem : ISubSystem
{
public string Id => "Delayed SubModule";
- public string Description => "Mod Developer feature! Provides helpers to run methods after SubModule events.";
+ public string Name => "{=joCJ9xpDvM}Delayed SubModule";
+ public string Description => "{=Gznum6kuzv}Mod Developer feature! Provides helpers to run methods after SubModule events.";
public bool IsEnabled => true;
public bool CanBeDisabled => false;
public bool CanBeSwitchedAtRuntime => false;
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs b/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs
index 7f76cfba..ced6b8a7 100644
--- a/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs
+++ b/src/Bannerlord.ButterLib/ExceptionHandler/BEWPatch.cs
@@ -1,17 +1,12 @@
-using Bannerlord.BLSE;
-using Bannerlord.ButterLib.Common.Extensions;
-using Bannerlord.ButterLib.ExceptionHandler.DebuggerDetection;
+using Bannerlord.ButterLib.ExceptionHandler.DebuggerDetection;
using HarmonyLib;
using HarmonyLib.BUTR.Extensions;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -28,7 +23,6 @@ namespace Bannerlord.ButterLib.ExceptionHandler
// TaleWorlds.MountAndBlade.MissionBehaviour:OnMissionTick -> Called by TaleWorlds.MountAndBlade.Mission:Tick
// TaleWorlds.MountAndBlade.MBSubModuleBase:OnSubModuleLoad -> Replicated
- [BLSELoaderInterceptor]
internal sealed class BEWPatch
{
public static bool IsDebuggerAttached()
@@ -37,9 +31,7 @@ public static bool IsDebuggerAttached()
return true;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
return ProcessDebug.CheckProcessDebugObjectHandle();
- }
return false;
}
@@ -54,8 +46,6 @@ internal record ExceptionIdentifier(Type Type, string? StackTrace, string Messag
private static readonly string[] BEW = { "org.calradia.admiralnelson.betterexceptionwindow" };
- //private static readonly Assembly[] AutoGeneratedAssemblies = AccessTools2.AllAssemblies().Where(x => x.GetName().Name.EndsWith(".AutoGeneratedAssemblies")).ToArray();
-
private static readonly MethodInfo? ManagedApplicationTickMethod = AccessTools2.Method("TaleWorlds.DotNet.Managed:ApplicationTick");
private static readonly MethodInfo? ModuleOnApplicationTickMethod = AccessTools2.Method("TaleWorlds.MountAndBlade.Module:OnApplicationTick");
private static readonly MethodInfo? ScreenManagerTickMethod = AccessTools2.Method("TaleWorlds.ScreenSystem.ScreenManager:Tick");
@@ -63,13 +53,6 @@ internal record ExceptionIdentifier(Type Type, string? StackTrace, string Messag
private static readonly MethodInfo? MissionTickMethod = AccessTools2.Method("TaleWorlds.MountAndBlade.Mission:Tick");
public static readonly MethodInfo? FinalizerMethod = AccessTools2.Method(typeof(BEWPatch), nameof(Finalizer));
- private static readonly AccessTools.FieldRef>? LoadedSubModuleTypes =
- AccessTools2.FieldRefAccess>("_loadedSubmoduleTypes");
-
- private static ILogger _log = default!;
-
- private static bool _wasButrLoaderInterceptorCalled = false;
-
private static void Finalizer(Exception? __exception)
{
if (ExceptionHandlerSubSystem.Instance?.DisableWhenDebuggerIsAttached == true && IsDebuggerAttached())
@@ -81,9 +64,6 @@ private static void Finalizer(Exception? __exception)
internal static void Enable(Harmony harmony)
{
- _log = ButterLibSubModule.Instance?.GetServiceProvider()?.GetRequiredService>()
- ?? NullLogger.Instance;
-
harmony.Patch(ManagedApplicationTickMethod, finalizer: new HarmonyMethod(FinalizerMethod, before: BEW));
harmony.Patch(ModuleOnApplicationTickMethod, finalizer: new HarmonyMethod(FinalizerMethod, before: BEW));
harmony.Patch(ScreenManagerTickMethod, finalizer: new HarmonyMethod(FinalizerMethod, before: BEW));
@@ -114,79 +94,32 @@ internal static void Enable(Harmony harmony)
transpiler: AccessTools2.Method(typeof(BEWPatch), nameof(BlankTranspiler)));
}
- internal static void Disable(Harmony harmony)
- {
- harmony.Unpatch(ManagedApplicationTickMethod, FinalizerMethod);
- harmony.Unpatch(ModuleOnApplicationTickMethod, FinalizerMethod);
- harmony.Unpatch(ScreenManagerTickMethod, FinalizerMethod);
- harmony.Unpatch(ManagedScriptHolderTickComponentsMethod, FinalizerMethod);
- harmony.Unpatch(MissionTickMethod, FinalizerMethod);
- }
-
- /*
- internal static void EnableWithDebug(Harmony harmony)
+ internal static void EnableAutoGenCatch(Harmony harmony)
{
- _log = ButterLibSubModule.Instance?.GetServiceProvider()?.GetRequiredService>()
- ?? NullLogger.Instance;
-
- harmony.Patch(ModuleOnApplicationTickMethod, finalizer: new HarmonyMethod(FinalizerMethod, before: BEW));
- harmony.Patch(MissionTickMethod, finalizer: new HarmonyMethod(FinalizerMethod, before: BEW));
-
- var callbacksGeneratedTypes = AutoGeneratedAssemblies.SelectMany(x => x.GetTypes().Where(y => y.Name.EndsWith("CallbacksGenerated")));
+ var callbacksGeneratedTypes = AccessTools2.AllAssemblies().SelectMany(x => x.GetTypes().Where(y => y.Name.EndsWith("CallbacksGenerated")));
var callbackGeneratedMethods = callbacksGeneratedTypes.SelectMany(AccessTools.GetDeclaredMethods);
foreach (var method in callbackGeneratedMethods.Where(x => x.GetCustomAttributesData().Any(y => y.AttributeType.Name == "MonoPInvokeCallbackAttribute")))
harmony.Patch(method, finalizer: new HarmonyMethod(FinalizerMethod, before: BEW));
-
- if (!_wasButrLoaderInterceptorCalled)
- PatchSubModules(harmony);
}
- internal static void DisableWithDebug(Harmony harmony)
+ internal static void Disable(Harmony harmony)
{
+ harmony.Unpatch(ManagedApplicationTickMethod, FinalizerMethod);
harmony.Unpatch(ModuleOnApplicationTickMethod, FinalizerMethod);
+ harmony.Unpatch(ScreenManagerTickMethod, FinalizerMethod);
+ harmony.Unpatch(ManagedScriptHolderTickComponentsMethod, FinalizerMethod);
harmony.Unpatch(MissionTickMethod, FinalizerMethod);
+ }
- var callbacksGeneratedTypes = AutoGeneratedAssemblies.SelectMany(x => x.GetTypes().Where(y => y.Name.EndsWith("CallbacksGenerated")));
+ internal static void DisableAutoGenCatch(Harmony harmony)
+ {
+ var callbacksGeneratedTypes = AccessTools2.AllAssemblies().SelectMany(x => x.GetTypes().Where(y => y.Name.EndsWith("CallbacksGenerated")));
var callbackGeneratedMethods = callbacksGeneratedTypes.SelectMany(AccessTools.GetDeclaredMethods);
foreach (var method in callbackGeneratedMethods.Where(x => x.GetCustomAttributesData().Any(y => y.AttributeType.Name == "MonoPInvokeCallbackAttribute")))
harmony.Unpatch(method, FinalizerMethod);
}
- */
[MethodImpl(MethodImplOptions.NoInlining)]
private static IEnumerable BlankTranspiler(IEnumerable instructions) => instructions;
-
- ///
- /// We need to patch MBSubModuleBase.OnSubModuleLoad because they generally can't be catched.
- /// The reason is, Harmony can't patch a method it's running in.
- /// The exception handling (this one) is started within the
- /// Module.Initialize() -> Module.LoadSubModules() -> Module.InitializeSubModules() -> MBSubModuleBase.OnSubModuleLoad()
- /// We start the exception interception within this scope, so if anything is throwing while within Module.Initialize(),
- /// we will lose that. It's easier to intercept every exception in MBSubModuleBase.OnSubModuleLoad() instead.
- ///
- private static bool PatchSubModules(Harmony harmony)
- {
- /*
- if (LoadedSubModuleTypes is null)
- return false;
-
- foreach (var (_, type) in LoadedSubModuleTypes(Module.CurrentModule))
- {
- if (AccessTools2.Method(type, "OnSubModuleLoad") is not { } method || method.DeclaringType == typeof(MBSubModuleBase))
- continue;
-
- harmony.Patch(method, finalizer: new HarmonyMethod(FinalizerMethod, before: BEW));
- }
- */
- return true;
- }
-
- // BUTRLoader gives un the ability to intercept every exception call.
- // We will use the earlier entrypoint instead
- private static void OnInitializeSubModulesPrefix()
- {
- _wasButrLoaderInterceptorCalled = true;
- PatchSubModules(new Harmony("Bannerlord.ButterLib.ExceptionHandler.BUTRLoadingInterceptor"));
- }
}
}
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/CloseHandleTrick.cs b/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/CloseHandleTrick.cs
deleted file mode 100644
index 5924daf6..00000000
--- a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/CloseHandleTrick.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-using System;
-using System.Runtime.InteropServices;
-
-namespace Bannerlord.ButterLib.ExceptionHandler.DebuggerDetection
-{
- ///
- /// Starting with Windows XP, Windows systems have had a mechanism for kernel object handle tracing.
- /// When the tracing mode is on, all operations with handlers are saved to the circular buffer, also,
- /// when trying to use a nonexistent handler, for instance to close it using the CloseHandle function,
- /// the EXCEPTION_INVALID_HANDLE exception will be generated. If a process is started not from the debugger,
- /// the CloseHandle function will return FALSE.
- /// It was originally published on https://www.apriorit.com/
- ///
- internal static class CloseHandleTrick
- {
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool CloseHandle(IntPtr hObject);
-
- public static bool Check()
- {
- try
- {
- if (IntPtr.Size == 8)
- CloseHandle((IntPtr) 0xDEADBEEF);
- else
- CloseHandle((IntPtr) 0xDEADBEE);
- return false;
- }
- catch
- {
- return true;
- }
- }
- }
-}
-*/
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/PEBBeingDebugged.cs b/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/PEBBeingDebugged.cs
deleted file mode 100644
index ad16cc7c..00000000
--- a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/PEBBeingDebugged.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-using System;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace Bannerlord.ButterLib.ExceptionHandler.DebuggerDetection
-{
- internal static class PEBBeingDebugged
- {
- private delegate IntPtr PebAddress();
-
- [DllImport("kernel32.dll")]
- private static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
-
- public static unsafe bool CheckPeb()
- {
- byte[] assembledCode;
- if (IntPtr.Size == 8)
- assembledCode = new byte[]
- {
- 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60, 0x00, // mov rax,QWORD PTR gs:0x60
- 0x00, 0x00, 0xC2, 0x00, 0x00 // ret 0x0
- };
- else
- assembledCode = new byte[]
- {
- 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, // mov eax,fs:0x30
- 0xC2, 0x00, 0x00 // ret 0x0
- };
-
- fixed (byte* ptr = assembledCode)
- {
- var memoryAddress = (IntPtr) ptr;
-
- if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, memoryAddress, (UIntPtr) assembledCode.Length, 0x40, out _)) // EXECUTE_READWRITE
- return false;
-
- var pebAddress = Marshal.GetDelegateForFunctionPointer(memoryAddress);
- var isDebuggerPresent = Convert.ToBoolean(Marshal.ReadByte(pebAddress(), 2));
- return isDebuggerPresent;
- }
- }
- }
-}
-*/
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/ProcessDebug.cs b/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/ProcessDebug.cs
index 4c262c8f..b284baed 100644
--- a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/ProcessDebug.cs
+++ b/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/ProcessDebug.cs
@@ -7,7 +7,6 @@ namespace Bannerlord.ButterLib.ExceptionHandler.DebuggerDetection
internal static class ProcessDebug
{
private const int PROCESS_DEBUG_OBJECT_HANDLE = 30;
- private const int PROCESS_DEBUG_PORT = 7;
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass,
@@ -31,26 +30,5 @@ public static bool CheckProcessDebugObjectHandle()
);
return status == 0 && (IntPtr) 0 != flProcessDebugObject;
}
-
- /*
- ///
- /// The CheckRemoteDebuggerPresent function is assigned the DebugPort value,
- /// as the ProcessInformationClass parameter value (the second one) is 7.
- /// It was originally published on https://www.apriorit.com/
- ///
- ///
- public static bool CheckProcessDebugPort()
- {
- var status = NtQueryInformationProcess
- (
- Process.GetCurrentProcess().Handle,
- PROCESS_DEBUG_PORT,
- out var flProcessDebugPort,
- IntPtr.Size,
- IntPtr.Zero
- );
- return status == 0 && (IntPtr) (-1) == flProcessDebugPort;
- }
- */
}
}
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/RaiseExceptionTrick.cs b/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/RaiseExceptionTrick.cs
deleted file mode 100644
index 0302a4e3..00000000
--- a/src/Bannerlord.ButterLib/ExceptionHandler/DebuggerDetection/RaiseExceptionTrick.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-using System;
-using System.Runtime.InteropServices;
-
-namespace Bannerlord.ButterLib.ExceptionHandler.DebuggerDetection
-{
- ///
- /// Since Windows 10, the implementation of the OutputDebugString function has changed to a
- /// simple RaiseException call with the specific parameters. So, debug output exception must be now handled by the debugger.
- /// There are two exception types: DBG_PRINTEXCEPTION_C (0x40010006) and DBG_PRINTEXCEPTION_W(0x4001000A),
- /// which can be used to detect the debugger presence.
- /// It was originally published on https://www.apriorit.com/
- ///
- internal static class RaiseExceptionTrick
- {
- private const uint DBG_PRINTEXCEPTION_C = 0x40010006;
- private const uint DBG_PRINTEXCEPTION_W = 0x4001000A;
-
- [DllImport("kernel32.dll")]
- private static extern bool RaiseException(uint dwExceptionCode, uint dwExceptionFlags, uint nNumberOfArguments, IntPtr lpArguments);
-
- [DllImport("kernel32.dll")]
- private static extern uint GetLastError();
-
- public static bool Check()
- {
- try
- {
- RaiseException(DBG_PRINTEXCEPTION_C, 0, 0, IntPtr.Zero);
- }
- catch
- {
- return GetLastError() == DBG_PRINTEXCEPTION_C;
- }
-
- return true;
- }
- }
-}
-*/
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionHandlerSubSystem.cs b/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionHandlerSubSystem.cs
index dfb943c2..5fe6ee20 100644
--- a/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionHandlerSubSystem.cs
+++ b/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionHandlerSubSystem.cs
@@ -1,4 +1,5 @@
-using Bannerlord.ButterLib.SubSystems;
+using Bannerlord.BLSE;
+using Bannerlord.ButterLib.SubSystems;
using Bannerlord.ButterLib.SubSystems.Settings;
using HarmonyLib;
@@ -6,9 +7,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.ExceptionServices;
+using System.Security;
namespace Bannerlord.ButterLib.ExceptionHandler
{
+ [BLSEInterceptor]
internal sealed class ExceptionHandlerSubSystem : ISubSystem, ISubSystemSettings
{
public static ExceptionHandlerSubSystem? Instance { get; private set; }
@@ -16,7 +20,8 @@ internal sealed class ExceptionHandlerSubSystem : ISubSystem, ISubSystemSettings
internal readonly Harmony Harmony = new("Bannerlord.ButterLib.ExceptionHandler.BEW");
public string Id => "ExceptionHandler";
- public string Description => "Captures game crashes and creates reports out of them.";
+ public string Name => "{=ZypQtNNcVN}Exception Handler";
+ public string Description => "{=UreeIeLQYS}Captures game crashes and creates reports out of them.";
public bool IsEnabled { get; private set; }
public bool CanBeDisabled => true;
public bool CanBeSwitchedAtRuntime => true;
@@ -56,50 +61,20 @@ private set
{
_catchAutoGenExceptions = value;
- /*
if (_catchAutoGenExceptions)
{
if (IsEnabled)
{
- BEWPatch.Disable(Harmony);
- BEWPatch.EnableWithDebug(Harmony);
+ //BEWPatch.Disable(Harmony);
+ BEWPatch.EnableAutoGenCatch(Harmony);
}
}
else
{
if (IsEnabled)
{
- BEWPatch.DisableWithDebug(Harmony);
- BEWPatch.Enable(Harmony);
- }
- }
- */
- }
- }
- }
-
- private bool _useVanillaCrashHandler = false;
- public bool UseVanillaCrashHandler
- {
- get => _useVanillaCrashHandler;
- private set
- {
- if (_useVanillaCrashHandler != value)
- {
- _useVanillaCrashHandler = value;
-
- if (_useVanillaCrashHandler)
- {
- if (IsEnabled)
- {
- WatchdogHandler.EnableTWWatchdog();
- }
- }
- else
- {
- if (IsEnabled)
- {
- WatchdogHandler.DisableTWWatchdog();
+ //BEWPatch.Enable(Harmony);
+ BEWPatch.DisableAutoGenCatch(Harmony);
}
}
}
@@ -117,10 +92,6 @@ private set
"{=jorWb502pD} Catch AutoGenerated Code Exceptions (Lower Performance) (DISABLED)",
"{=ji1brrsEZz} Catch every Native->Managed call. Should catch every exception not catched the standard way. Might decrease the overall performance a bit.",
x => x.CatchAutoGenExceptions),
- new SubSystemSettingsPropertyBool(
- "{=ZD69h3IpF5} Use Vanilla Crash Handler",
- "{=o0DgSNv5V1} Disables ButterLib's and BEW's Crash Handlers with the new Watchdog Crash Handler. Do not enable if not sure.",
- x => x.UseVanillaCrashHandler),
};
@@ -135,10 +106,12 @@ public void Enable()
if (!BEWPatch.IsDebuggerAttached())
SubscribeToUnhandledException();
-
- BEWPatch.Enable(Harmony);
-
- WatchdogHandler.DisableTWWatchdog();
+
+ if (!_wasButrLoaderInterceptorCalled)
+ {
+ BEWPatch.Enable(Harmony);
+ BEWPatch.EnableAutoGenCatch(Harmony);
+ }
}
public void Disable()
@@ -151,14 +124,14 @@ public void Disable()
{
BEWPatch.Disable(Harmony);
}
-
- WatchdogHandler.EnableTWWatchdog();
}
private static bool _isSubscribedToUnhandledException;
+ private static bool _wasButrLoaderInterceptorCalled;
+
private static void SubscribeToUnhandledException()
{
- if (!_isSubscribedToUnhandledException)
+ if (!_isSubscribedToUnhandledException && !_wasButrLoaderInterceptorCalled)
{
_isSubscribedToUnhandledException = true;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
@@ -166,13 +139,14 @@ private static void SubscribeToUnhandledException()
}
private static void UnsubscribeToUnhandledException()
{
- if (_isSubscribedToUnhandledException)
+ if (_isSubscribedToUnhandledException && !_wasButrLoaderInterceptorCalled)
{
_isSubscribedToUnhandledException = false;
AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
}
}
+ [HandleProcessCorruptedStateExceptions, SecurityCritical]
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is Exception exception)
@@ -180,5 +154,11 @@ private static void CurrentDomain_UnhandledException(object sender, UnhandledExc
ExceptionReporter.Show(exception);
}
}
+
+ // BLSE Duck typed method
+ private static void OnInitializeSubModulesPrefix()
+ {
+ _wasButrLoaderInterceptorCalled = true;
+ }
}
}
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionReporter.cs b/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionReporter.cs
index 242cc614..a1fc64be 100644
--- a/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionReporter.cs
+++ b/src/Bannerlord.ButterLib/ExceptionHandler/ExceptionReporter.cs
@@ -1,10 +1,15 @@
-using System;
+using Bannerlord.BLSE;
+
+using System;
using System.Diagnostics;
namespace Bannerlord.ButterLib.ExceptionHandler
{
+ [BLSEExceptionHandler]
public static class ExceptionReporter
{
+ private static void OnException(Exception exception) => Show(exception);
+
public static void Show(Exception exception)
{
if (BEWPatch.SuppressedExceptions.Contains(BEWPatch.ExceptionIdentifier.FromException(exception)))
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/HtmlBuilder.cs b/src/Bannerlord.ButterLib/ExceptionHandler/HtmlBuilder.cs
index 95432dc5..1c077099 100644
--- a/src/Bannerlord.ButterLib/ExceptionHandler/HtmlBuilder.cs
+++ b/src/Bannerlord.ButterLib/ExceptionHandler/HtmlBuilder.cs
@@ -747,7 +747,7 @@ private static string GetLogFilesListHtml(CrashReport crashReport)
var sb = new StringBuilder();
sb.AppendLine("");
- foreach (var logSource in ButterLibSubModule.Instance?.GetServiceProvider().GetRequiredService>() ?? Enumerable.Empty())
+ foreach (var logSource in ButterLibSubModule.Instance?.GetServiceProvider()?.GetRequiredService>() ?? Enumerable.Empty())
{
sb.Append("- ").Append("").Append(logSource.Name).Append("").Append("
");
diff --git a/src/Bannerlord.ButterLib/ExceptionHandler/WatchdogHandler.cs b/src/Bannerlord.ButterLib/ExceptionHandler/WatchdogHandler.cs
deleted file mode 100644
index 6e696d44..00000000
--- a/src/Bannerlord.ButterLib/ExceptionHandler/WatchdogHandler.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System;
-using System.IO;
-using System.Runtime.InteropServices;
-
-namespace Bannerlord.ButterLib.ExceptionHandler
-{
- internal static unsafe class WatchdogHandler
- {
- [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- private static extern byte* LoadLibrary(string libname);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool VirtualProtect(byte* address, nint dwSize, int newProtect, out int oldProtect);
-
- private static readonly int PAGE_EXECUTE_READWRITE = 0x40;
-
- private static readonly string WatchdogLibraryName = "TaleWorlds.Native.dll";
- private static readonly byte[] WatchdogOriginal = "Watchdog.exe"u8.ToArray();
- private static readonly byte[] WatchdogReplacement = "Wetchdog.exe"u8.ToArray();
-
- // Disable Watchdog by renaming it, thus performing a soft delete in it's eyes
- public static void DisableTWWatchdog()
- {
- var watchdogLibraryFile = new FileInfo(WatchdogLibraryName);
- if (!watchdogLibraryFile.Exists) return;
-
- var libraryPtr = LoadLibrary(WatchdogLibraryName);
- // Don't like the fact that I can't get the concrete memory size
- var size = (int) watchdogLibraryFile.Length;
-
- var librarySpan = new ReadOnlySpan(libraryPtr, size);
-
- var searchSpan = librarySpan;
- var searchSpanOffset = 0;
- while (searchSpan.IndexOf(WatchdogOriginal) is var idx and not -1)
- {
- var watchdogLocationPtr = libraryPtr + searchSpanOffset + idx;
- var watchdogLocationSpan = new Span(watchdogLocationPtr, WatchdogOriginal.Length);
-
- VirtualProtect(watchdogLocationPtr, watchdogLocationSpan.Length, PAGE_EXECUTE_READWRITE, out var old);
- WatchdogReplacement.CopyTo(watchdogLocationSpan);
- VirtualProtect(watchdogLocationPtr, watchdogLocationSpan.Length, old, out _);
-
- searchSpanOffset = idx;
- searchSpan = searchSpan.Slice(searchSpanOffset);
- }
- }
-
- public static void EnableTWWatchdog()
- {
- var watchdogLibraryFile = new FileInfo(WatchdogLibraryName);
- if (!watchdogLibraryFile.Exists) return;
-
- var libraryPtr = LoadLibrary(WatchdogLibraryName);
- // Don't like the fact that I can't get the concrete memory size
- var size = (int) watchdogLibraryFile.Length;
-
- var librarySpan = new ReadOnlySpan(libraryPtr, size);
-
- var searchSpan = librarySpan;
- var searchSpanOffset = 0;
- while (searchSpan.IndexOf(WatchdogReplacement) is var idx and not -1)
- {
- var watchdogLocationPtr = libraryPtr + searchSpanOffset + idx;
- var watchdogLocationSpan = new Span(watchdogLocationPtr, WatchdogOriginal.Length);
-
- VirtualProtect(watchdogLocationPtr, watchdogLocationSpan.Length, PAGE_EXECUTE_READWRITE, out var old);
- WatchdogOriginal.CopyTo(watchdogLocationSpan);
- VirtualProtect(watchdogLocationPtr, watchdogLocationSpan.Length, old, out _);
-
- searchSpanOffset = idx;
- searchSpan = searchSpan.Slice(searchSpanOffset);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/Helpers/BLSEExceptionHandlerAttribute.cs b/src/Bannerlord.ButterLib/Helpers/BLSEExceptionHandlerAttribute.cs
new file mode 100644
index 00000000..16047210
--- /dev/null
+++ b/src/Bannerlord.ButterLib/Helpers/BLSEExceptionHandlerAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Bannerlord.BLSE
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class BLSEExceptionHandlerAttribute : Attribute { }
+}
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/Helpers/BLSELoaderInterceptorAttribute.cs b/src/Bannerlord.ButterLib/Helpers/BLSEInterceptorAttribute.cs
similarity index 64%
rename from src/Bannerlord.ButterLib/Helpers/BLSELoaderInterceptorAttribute.cs
rename to src/Bannerlord.ButterLib/Helpers/BLSEInterceptorAttribute.cs
index 0aec301b..67416b08 100644
--- a/src/Bannerlord.ButterLib/Helpers/BLSELoaderInterceptorAttribute.cs
+++ b/src/Bannerlord.ButterLib/Helpers/BLSEInterceptorAttribute.cs
@@ -4,5 +4,5 @@
namespace Bannerlord.BLSE
{
[AttributeUsage(AttributeTargets.Class)]
- internal sealed class BLSELoaderInterceptorAttribute : Attribute { }
+ internal sealed class BLSEInterceptorAttribute : Attribute { }
}
\ No newline at end of file
diff --git a/src/Bannerlord.ButterLib/SubModuleWrappers2/SubModuleWrappers2SubSystem.cs b/src/Bannerlord.ButterLib/SubModuleWrappers2/SubModuleWrappers2SubSystem.cs
index 8dcf3199..8de2cdaa 100644
--- a/src/Bannerlord.ButterLib/SubModuleWrappers2/SubModuleWrappers2SubSystem.cs
+++ b/src/Bannerlord.ButterLib/SubModuleWrappers2/SubModuleWrappers2SubSystem.cs
@@ -12,7 +12,8 @@ internal sealed class SubModuleWrappers2SubSystem : ISubSystem
private readonly Harmony Harmony = new("Bannerlord.ButterLib.SubModuleWrappers2");
public string Id => "SubModuleWrappers2";
- public string Description => "Mod Developer feature! A wrapper for MBSubModuleBase based on Harmony patches.";
+ public string Name => "{=NkAAB8EEu2}SubModule Wrappers";
+ public string Description => "{=izmKJPjkjN}Mod Developer feature! A wrapper for MBSubModuleBase based on Harmony patches.";
public bool IsEnabled => true;
public bool CanBeDisabled => false;
public bool CanBeSwitchedAtRuntime => false;
diff --git a/src/Bannerlord.ButterLib/SubSystems/ISubSystem.cs b/src/Bannerlord.ButterLib/SubSystems/ISubSystem.cs
index f9f37df7..62cbf87f 100644
--- a/src/Bannerlord.ButterLib/SubSystems/ISubSystem.cs
+++ b/src/Bannerlord.ButterLib/SubSystems/ISubSystem.cs
@@ -3,6 +3,7 @@
public interface ISubSystem
{
string Id { get; }
+ string Name { get; }
string Description { get; }
bool IsEnabled { get; }
bool CanBeDisabled { get; }