Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TheEye v1.2.9
plugins/BlackBox.WubarrksEye.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BlackBox.WubarrksEye.AbyssalLedger; using BlackBox.WubarrksEye.AbyssalLedger.Aggregates; using BlackBox.WubarrksEye.AbyssalLedger.Archive; using BlackBox.WubarrksEye.AbyssalLedger.Candidates; using BlackBox.WubarrksEye.AbyssalLedger.Evidence; using BlackBox.WubarrksEye.AbyssalLedger.Promotions; using BlackBox.WubarrksEye.Adapters; using BlackBox.WubarrksEye.Codex; using BlackBox.WubarrksEye.Core; using BlackBox.WubarrksEye.Core.Commands; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("BlackBox.WubarrksEye")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BlackBox.WubarrksEye")] [assembly: AssemblyTitle("BlackBox.WubarrksEye")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class DeepReflectionWalker { private sealed class ReferenceEqualityComparer : IEqualityComparer<object> { public static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer(); public new bool Equals(object x, object y) { return x == y; } public int GetHashCode(object obj) { return RuntimeHelpers.GetHashCode(obj); } } [CompilerGenerated] private sealed class <SafeFields>d__8 : IEnumerable<FieldInfo>, IEnumerable, IEnumerator<FieldInfo>, IDisposable, IEnumerator { private int <>1__state; private FieldInfo <>2__current; private int <>l__initialThreadId; private Type t; public Type <>3__t; private FieldInfo[] <>7__wrap1; private int <>7__wrap2; FieldInfo IEnumerator<FieldInfo>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SafeFields>d__8(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0083; } <>1__state = -1; FieldInfo[] fields; try { fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } catch { return false; } <>7__wrap1 = fields; <>7__wrap2 = 0; goto IL_0091; IL_0091: if (<>7__wrap2 < <>7__wrap1.Length) { FieldInfo fieldInfo = <>7__wrap1[<>7__wrap2]; if (!fieldInfo.IsStatic && !fieldInfo.FieldType.IsPointer && !IsForbidden(fieldInfo.FieldType)) { <>2__current = fieldInfo; <>1__state = 1; return true; } goto IL_0083; } <>7__wrap1 = null; return false; IL_0083: <>7__wrap2++; goto IL_0091; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<FieldInfo> IEnumerable<FieldInfo>.GetEnumerator() { <SafeFields>d__8 <SafeFields>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <SafeFields>d__ = this; } else { <SafeFields>d__ = new <SafeFields>d__8(0); } <SafeFields>d__.t = <>3__t; return <SafeFields>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<FieldInfo>)this).GetEnumerator(); } } private const int MAX_DEPTH = 32; private const int MAX_ITEMS = 500000; private static readonly HashSet<object> _visited = new HashSet<object>(ReferenceEqualityComparer.Instance); private static int _count; private static readonly string[] ForbiddenTypePrefixes = new string[35] { "PlayFab", "Steamworks", "UnityEngine.Networking", "UnityEngine.ResourceRequest", "UnityEngine.AsyncOperation", "System.Runtime.CompilerServices", "System.Threading", "System.Net", "System.IO", "System.Reflection.Emit", "System.Security", "System.Diagnostics", "System.Runtime.Remoting", "System.Runtime.InteropServices", "System.Runtime.Serialization", "System.Runtime.ExceptionServices", "System.Runtime.ConstrainedExecution", "System.Runtime.Versioning", "System.Runtime.Loader", "System.Runtime.GCSettings", "System.RuntimeType", "System.RuntimeTypeHandle", "System.RuntimeFieldHandle", "System.RuntimeMethodHandle", "System.RuntimeArgumentHandle", "System.RuntimeMethodInfoStub", "System.RuntimePropertyInfoStub", "System.RuntimeEventInfoStub", "System.RuntimeConstructorInfoStub", "System.RuntimeType+", "System.Runtime.CompilerServices.AsyncTaskMethodBuilder", "<>", "c__DisplayClass", "d__", "PrivateImplementationDetails" }; public static void Walk(object root, Action<string, object> onField) { _visited.Clear(); _count = 0; WalkInternal(root, "root", 0, onField); } private static void WalkInternal(object obj, string path, int depth, Action<string, object> onField) { if (obj == null || depth > 32 || _count++ > 500000) { return; } Type type = obj.GetType(); if (IsForbidden(type)) { return; } Object val = (Object)((obj is Object) ? obj : null); if ((val != null && (val == (Object)null || !Object.op_Implicit(val))) || !_visited.Add(obj)) { return; } onField(path, obj); foreach (FieldInfo item in SafeFields(type)) { try { object value = item.GetValue(obj); if (value != null) { string path2 = path + "." + item.Name; WalkInternal(value, path2, depth + 1, onField); } } catch { } } if (!(obj is IEnumerable enumerable) || obj is string) { return; } int num = 0; foreach (object item2 in enumerable) { if (item2 != null) { WalkInternal(item2, path + "[" + num + "]", depth + 1, onField); num++; } } } private static bool IsForbidden(Type t) { string text = t.FullName ?? t.Name; string[] forbiddenTypePrefixes = ForbiddenTypePrefixes; foreach (string value in forbiddenTypePrefixes) { if (text.StartsWith(value, StringComparison.Ordinal)) { return true; } } return false; } [IteratorStateMachine(typeof(<SafeFields>d__8))] private static IEnumerable<FieldInfo> SafeFields(Type t) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SafeFields>d__8(-2) { <>3__t = t }; } } namespace BlackBox.WubarrksEye { [BepInPlugin("blackbox.wubarrkseye", "Wubarrk's Eye", "1.2.8")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "blackbox.wubarrkseye"; public const string PluginName = "Wubarrk's Eye"; public const string PluginVersion = "1.2.8"; private Harmony _harmony; private static ManualLogSource _log; private static AbyssalLedgerRuntime _ledgerRuntime; public static ManualLogSource Log => _log; public static AbyssalLedgerRuntime LedgerRuntime => _ledgerRuntime; private void Awake() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; try { BlackBoxConfig.Bind(((BaseUnityPlugin)this).Config); _log.LogInfo((object)"[Eye] BlackBoxConfig bound."); _harmony = new Harmony("blackbox.wubarrkseye"); _harmony.PatchAll(); _log.LogInfo((object)"[Eye] Harmony patches applied."); HarmonyIntelligence.Initialize(_harmony, ((BaseUnityPlugin)this).Logger); AbyssalLedgerRuntime.Initialize(); CodexBootstrapper.Initialize(); DumpRuntime.Initialize(((BaseUnityPlugin)this).Logger); InitializeAbyssalLedger(); if (_ledgerRuntime != null) { EyeDumpNotifier.Initialize(((BaseUnityPlugin)this).Logger, _ledgerRuntime); } else { _log.LogWarning((object)"[Eye] AbyssalLedgerRuntime is null; EyeDumpNotifier not initialized."); } EyeCommands.Initialize(((BaseUnityPlugin)this).Logger); BootSplash.Initialize(((BaseUnityPlugin)this).Logger); HarmonyIntelligence.HarmonyTelemetry harmony = HarmonyIntelligence.CaptureSnapshot(); LedgerSnapshot ledger = ((_ledgerRuntime != null) ? _ledgerRuntime.BuildSnapshot() : LedgerSnapshot.Empty()); CodexBootstrapper.RefreshSnapshot(); CodexSnapshot codex = CodexBootstrapper.Snapshot ?? CodexSnapshot.Empty(); DumpSnapshot dump = DumpRuntime.BuildSnapshot(); BootSplash.Render(harmony, ledger, codex, dump); _log.LogInfo((object)"[Eye] Plugin initialization complete. Wubarrk's Eye is now watching."); } catch (Exception arg) { _log.LogError((object)$"[Eye] Plugin initialization failed: {arg}"); } } private void OnDestroy() { try { if (_harmony != null) { _harmony.UnpatchSelf(); _log.LogInfo((object)"[Eye] Harmony patches unpatched on destroy."); } } catch (Exception arg) { _log.LogError((object)$"[Eye] Failed during OnDestroy: {arg}"); } } private static void InitializeAbyssalLedger() { try { _ledgerRuntime = AbyssalLedgerRuntime.Initialize(AbyssalLedgerConfig.CreateDefault()); _ledgerRuntime.CodexPromotionAdapter = CandidateToCodexPromotion; ManualLogSource log = _log; if (log != null) { log.LogInfo((object)"[Eye][Ledger] Abyssal Ledger runtime initialized and Codex promotion adapter wired."); } } catch (Exception ex) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogError((object)("[Eye][Ledger] Failed to initialize Abyssal Ledger runtime: " + ex.Message)); } _ledgerRuntime = null; } } private static (bool succeeded, string status, string note, string error) CandidateToCodexPromotion(CandidateEntry candidate) { try { return CodexPromotionAdapter.PromoteCandidate(candidate); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogError((object)$"[Eye][Codex] Candidate promotion failed: {ex}"); } return (false, "error", "Codex promotion threw exception", ex.Message); } } public static void NotifyDumpCreated(int dumpId, string dumpFolderPath) { try { EyeDumpNotifier.NotifyDumpCreated(dumpId, dumpFolderPath); } catch (Exception arg) { ManualLogSource log = _log; if (log != null) { log.LogError((object)$"[Eye] NotifyDumpCreated failed for dumpId={dumpId}: {arg}"); } } } public static void RequestLedgerBackup(string note = null) { if (_ledgerRuntime == null) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)"[Eye][Ledger] RequestLedgerBackup called, but runtime is null."); } return; } try { string note2 = note ?? string.Empty; _ledgerRuntime.CreateBackup(note2); ManualLogSource log2 = _log; if (log2 != null) { log2.LogInfo((object)"[Eye][Ledger] Backup request processed."); } } catch (Exception arg) { ManualLogSource log3 = _log; if (log3 != null) { log3.LogError((object)$"[Eye][Ledger] RequestLedgerBackup failed: {arg}"); } } } } } namespace BlackBox.WubarrksEye.HarmonyPatches { internal static class HarmonyBootstrap { public static void ApplyAll(Harmony harmony) { if (harmony == null) { throw new ArgumentNullException("harmony"); } try { Assembly assembly = typeof(HarmonyBootstrap).Assembly; BlackBoxLogger.Info("[HarmonyBootstrap] Running PatchAllSafe for attribute-based patches..."); HarmonyPatcher.PatchAllSafe(harmony, assembly); int num = harmony.GetPatchedMethods().Count(); BlackBoxLogger.Info($"[HarmonyBootstrap] Total patched methods after bootstrap: {num}"); } catch (Exception arg) { BlackBoxLogger.Warn($"[HarmonyBootstrap] Fatal error while applying patches: {arg}"); } } } internal static class HarmonyPatcher { [CompilerGenerated] private sealed class <FindSimilarNamedMethods>d__14 : IEnumerable<MethodInfo>, IEnumerable, IEnumerator<MethodInfo>, IDisposable, IEnumerator { private int <>1__state; private MethodInfo <>2__current; private int <>l__initialThreadId; private Type type; public Type <>3__type; private string methodName; public string <>3__methodName; private string <target>5__2; private MethodInfo[] <>7__wrap2; private int <>7__wrap3; MethodInfo IEnumerator<MethodInfo>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FindSimilarNamedMethods>d__14(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <target>5__2 = null; <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00c2; } <>1__state = -1; MethodInfo[] methods; try { methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch { return false; } <target>5__2 = methodName.ToLowerInvariant(); <>7__wrap2 = methods; <>7__wrap3 = 0; goto IL_00d0; IL_00d0: if (<>7__wrap3 < <>7__wrap2.Length) { MethodInfo methodInfo = <>7__wrap2[<>7__wrap3]; string text = methodInfo.Name.ToLowerInvariant(); if (!(text == <target>5__2) && (text.Contains(<target>5__2) || <target>5__2.Contains(text) || LevenshteinDistance(text, <target>5__2) <= 2)) { <>2__current = methodInfo; <>1__state = 1; return true; } goto IL_00c2; } <>7__wrap2 = null; return false; IL_00c2: <>7__wrap3++; goto IL_00d0; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodInfo> IEnumerable<MethodInfo>.GetEnumerator() { <FindSimilarNamedMethods>d__14 <FindSimilarNamedMethods>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <FindSimilarNamedMethods>d__ = this; } else { <FindSimilarNamedMethods>d__ = new <FindSimilarNamedMethods>d__14(0); } <FindSimilarNamedMethods>d__.type = <>3__type; <FindSimilarNamedMethods>d__.methodName = <>3__methodName; return <FindSimilarNamedMethods>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodInfo>)this).GetEnumerator(); } } public static int PatchAllOverloads(Harmony harmony, Type targetType, string methodName, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null) { if (harmony == null) { throw new ArgumentNullException("harmony"); } if (targetType == null) { throw new ArgumentNullException("targetType"); } if (string.IsNullOrEmpty(methodName)) { throw new ArgumentNullException("methodName"); } MethodInfo[] array; try { array = (from m in targetType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where string.Equals(m.Name, methodName, StringComparison.Ordinal) select m).ToArray(); } catch (Exception ex) { LoggerWarning("PatchAllOverloads: failed to enumerate methods on " + targetType.FullName + ": " + ex.Message); return 0; } if (array.Length == 0) { array = FindSimilarNamedMethods(targetType, methodName).ToArray(); if (array.Length == 0) { LoggerDebug("PatchAllOverloads: no methods named or similar to '" + methodName + "' found on " + targetType.FullName + "."); return 0; } LoggerWarning("PatchAllOverloads: exact method '" + methodName + "' not found on " + targetType.FullName + ". " + string.Format("Using {0} similar method(s): {1}", array.Length, string.Join(", ", array.Select((MethodInfo m) => m.Name)))); } int num = 0; MethodInfo[] array2 = array; foreach (MethodInfo methodInfo in array2) { if (!IsPatchable(methodInfo)) { LoggerDebug("PatchAllOverloads: skipping non-patchable " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + ")"); continue; } try { harmony.Patch((MethodBase)methodInfo, prefix, postfix, transpiler, (HarmonyMethod)null, (HarmonyMethod)null); num++; LoggerInfo("Patched " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + ")"); } catch (Exception ex2) { LoggerWarning("PatchAllOverloads: failed to patch " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + "): " + ex2.Message); } } return num; } public static bool PatchSpecificOverload(Harmony harmony, Type targetType, string methodName, Type[] parameterTypes, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null) { if (harmony == null) { throw new ArgumentNullException("harmony"); } if (targetType == null) { throw new ArgumentNullException("targetType"); } if (string.IsNullOrEmpty(methodName)) { throw new ArgumentNullException("methodName"); } parameterTypes = parameterTypes ?? Type.EmptyTypes; MethodInfo methodInfo = null; try { methodInfo = targetType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null); } catch (AmbiguousMatchException) { LoggerWarning("PatchSpecificOverload: ambiguous match for " + targetType.FullName + "." + methodName + "(" + string.Join(", ", parameterTypes.Select((Type t) => t?.Name ?? "null")) + "). Consider PatchAllOverloads."); return false; } catch (Exception ex2) { LoggerWarning("PatchSpecificOverload: error resolving " + targetType.FullName + "." + methodName + ": " + ex2.Message); return false; } if (methodInfo == null) { methodInfo = FindMethodBySignatureShape(targetType, methodName, parameterTypes); if (methodInfo == null) { LoggerDebug("PatchSpecificOverload: method not found " + targetType.FullName + "." + methodName + "(" + string.Join(", ", parameterTypes.Select((Type t) => t?.Name ?? "null")) + ")."); return false; } LoggerWarning("PatchSpecificOverload: using fallback method " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + ") instead of missing " + methodName + "."); } if (!IsPatchable(methodInfo)) { LoggerWarning("PatchSpecificOverload: method " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + ") is not patchable (abstract/extern/no body)."); return false; } try { harmony.Patch((MethodBase)methodInfo, prefix, postfix, transpiler, (HarmonyMethod)null, (HarmonyMethod)null); LoggerInfo("Patched specific overload " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + ")"); return true; } catch (Exception ex3) { LoggerWarning("PatchSpecificOverload: failed to patch " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + "): " + ex3.Message); return false; } } public static int SafePatchMethods(Harmony harmony, IEnumerable<MethodBase> methods, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null) { if (harmony == null) { throw new ArgumentNullException("harmony"); } if (methods == null) { throw new ArgumentNullException("methods"); } int num = 0; foreach (MethodBase method in methods) { if (method == null) { continue; } if (!IsPatchable(method)) { LoggerDebug("SafePatchMethods: skipping non-patchable " + method.DeclaringType?.FullName + "." + method.Name + "(" + ParamTypes(method) + ")"); continue; } try { harmony.Patch(method, prefix, postfix, transpiler, (HarmonyMethod)null, (HarmonyMethod)null); num++; LoggerInfo("Patched " + method.DeclaringType?.FullName + "." + method.Name + "(" + ParamTypes(method) + ")"); } catch (Exception ex) { LoggerWarning("SafePatchMethods: failed to patch " + method.DeclaringType?.FullName + "." + method.Name + "(" + ParamTypes(method) + "): " + ex.Message); } } return num; } public static void PatchAllSafe(Harmony harmony, Assembly assembly) { if (harmony == null) { throw new ArgumentNullException("harmony"); } if (assembly == null) { throw new ArgumentNullException("assembly"); } Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } catch (Exception ex2) { LoggerWarning("PatchAllSafe: failed to enumerate types in assembly: " + ex2.Message); return; } int num = 0; Type[] array2 = array; foreach (Type type in array2) { if (type == null || !type.IsClass) { continue; } object[] array3 = type.GetCustomAttributes(inherit: false).Where(delegate(object a) { string? fullName = a.GetType().FullName; return (fullName != null && fullName.StartsWith("HarmonyLib.HarmonyPatch")) || (a.GetType().FullName?.Contains("HarmonyPatch") ?? false); }).ToArray(); if (array3.Length != 0) { try { int num2 = SafePatchClass(harmony, type, array3); num += num2; } catch (Exception ex3) { LoggerWarning("PatchAllSafe: error processing patch class " + type.FullName + ": " + ex3.Message); } } } LoggerInfo($"PatchAllSafe: completed. Total patched methods: {num}"); } private static int SafePatchClass(Harmony harmony, Type patchClass, object[] patchAttrs) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (harmony == null) { throw new ArgumentNullException("harmony"); } if (patchClass == null) { throw new ArgumentNullException("patchClass"); } int patchedCount = 0; if (patchAttrs.Any((object a) => a.GetType().Name == "HarmonyPatchAllAttribute")) { LoggerDebug("SafePatchClass: skipping HarmonyPatchAll on " + patchClass.FullName + " (too broad)."); return 0; } object[] array = patchAttrs.Where((object a) => a.GetType().Name == "HarmonyPatchAttribute").ToArray(); if (array.Length == 0) { try { new PatchClassProcessor(harmony, patchClass).Patch(); LoggerInfo("SafePatchClass: PatchClassProcessor applied for " + patchClass.FullName + "."); return 1; } catch (Exception ex) { LoggerWarning("SafePatchClass: PatchClassProcessor failed for " + patchClass.FullName + ": " + ex.Message); return 0; } } object[] array2 = array; foreach (object attr in array2) { try { if (!TryProcessHarmonyPatchAttribute(harmony, patchClass, attr, ref patchedCount)) { LoggerDebug("SafePatchClass: HarmonyPatch on " + patchClass.FullName + " could not be resolved; skipped."); } } catch (Exception ex2) { LoggerWarning("SafePatchClass: error processing HarmonyPatch attribute on " + patchClass.FullName + ": " + ex2.Message); } } return patchedCount; } private static bool TryProcessHarmonyPatchAttribute(Harmony harmony, Type patchClass, object attr, ref int patchedCount) { Type type = attr.GetType(); PropertyInfo propertyInfo = type.GetProperty("info") ?? type.GetProperty("Info"); if (propertyInfo != null) { object value = propertyInfo.GetValue(attr); if (value != null) { return ProcessHarmonyPatchInfo(harmony, patchClass, value, ref patchedCount); } } FieldInfo? obj = type.GetField("declaringType") ?? type.GetField("DeclaringType"); FieldInfo fieldInfo = type.GetField("methodName") ?? type.GetField("MethodName"); FieldInfo fieldInfo2 = type.GetField("argumentTypes") ?? type.GetField("ArgumentTypes"); Type type2 = obj?.GetValue(attr) as Type; string text = fieldInfo?.GetValue(attr) as string; Type[] argTypes = fieldInfo2?.GetValue(attr) as Type[]; if (type2 == null || string.IsNullOrEmpty(text)) { return false; } return ProcessTargetSpec(harmony, patchClass, type2, text, argTypes, ref patchedCount); } private static bool ProcessHarmonyPatchInfo(Harmony harmony, Type patchClass, object info, ref int patchedCount) { Type type = info.GetType(); PropertyInfo propertyInfo = type.GetProperty("declaringType") ?? type.GetProperty("DeclaringType"); PropertyInfo propertyInfo2 = type.GetProperty("methodName") ?? type.GetProperty("MethodName"); PropertyInfo propertyInfo3 = type.GetProperty("argumentTypes") ?? type.GetProperty("ArgumentTypes"); Type type2 = null; string text = null; Type[] argTypes = null; if (propertyInfo != null) { type2 = propertyInfo.GetValue(info) as Type; } if (propertyInfo2 != null) { text = propertyInfo2.GetValue(info) as string; } if (propertyInfo3 != null) { argTypes = propertyInfo3.GetValue(info) as Type[]; } if (type2 == null || string.IsNullOrEmpty(text)) { return false; } return ProcessTargetSpec(harmony, patchClass, type2, text, argTypes, ref patchedCount); } private static bool ProcessTargetSpec(Harmony harmony, Type patchClass, Type targetType, string methodName, Type[] argTypes, ref int patchedCount) { HarmonyMethod harmonyMethodFromPatchClass = GetHarmonyMethodFromPatchClass(patchClass, "Prefix"); HarmonyMethod harmonyMethodFromPatchClass2 = GetHarmonyMethodFromPatchClass(patchClass, "Postfix"); HarmonyMethod harmonyMethodFromPatchClass3 = GetHarmonyMethodFromPatchClass(patchClass, "Transpiler"); if (argTypes != null && argTypes.Length != 0) { MethodInfo methodInfo = null; try { methodInfo = targetType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, argTypes, null); } catch (AmbiguousMatchException) { LoggerWarning("SafePatchClass: ambiguous match for " + targetType.FullName + "." + methodName + " with specified args; attempting signature-shape fallback."); } if (methodInfo == null) { methodInfo = FindMethodBySignatureShape(targetType, methodName, argTypes); } if (methodInfo == null) { LoggerDebug("SafePatchClass: method not found " + targetType.FullName + "." + methodName + "(" + string.Join(", ", argTypes.Select((Type t) => t?.Name ?? "null")) + ")."); return false; } if (!IsPatchable(methodInfo)) { LoggerDebug("SafePatchClass: target not patchable " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + "); skipping."); return false; } try { harmony.Patch((MethodBase)methodInfo, harmonyMethodFromPatchClass, harmonyMethodFromPatchClass2, harmonyMethodFromPatchClass3, (HarmonyMethod)null, (HarmonyMethod)null); patchedCount++; LoggerInfo("SafePatchClass: patched " + targetType.FullName + "." + methodInfo.Name + "(" + ParamTypes(methodInfo) + ") via " + patchClass.FullName); return true; } catch (Exception ex2) { LoggerWarning("SafePatchClass: failed to patch " + targetType.FullName + "." + methodInfo.Name + ": " + ex2.Message); return false; } } int num = PatchAllOverloads(harmony, targetType, methodName, harmonyMethodFromPatchClass, harmonyMethodFromPatchClass2, harmonyMethodFromPatchClass3); patchedCount += num; return num > 0; } private static HarmonyMethod GetHarmonyMethodFromPatchClass(Type patchClass, string methodName) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown try { MethodInfo method = patchClass.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return null; } return new HarmonyMethod(method); } catch { return null; } } public static bool IsPatchable(MethodBase method) { if (method == null) { return false; } if (method.IsAbstract) { return false; } if ((method.Attributes & MethodAttributes.PinvokeImpl) != 0) { return false; } MethodInfo methodInfo = method as MethodInfo; if (methodInfo != null) { try { if (methodInfo.GetMethodBody() == null) { return false; } } catch { return false; } } return true; } private static string ParamTypes(MethodBase m) { try { return string.Join(", ", from p in m.GetParameters() select p.ParameterType.Name); } catch { return ""; } } private static void LoggerInfo(string msg) { try { BlackBoxLogger.Info("[HarmonyPatcher] " + msg); } catch { } } private static void LoggerWarning(string msg) { try { BlackBoxLogger.Warn("[HarmonyPatcher] " + msg); } catch { } } private static void LoggerDebug(string msg) { try { BlackBoxLogger.Info("[HarmonyPatcher][Debug] " + msg); } catch { } } [IteratorStateMachine(typeof(<FindSimilarNamedMethods>d__14))] private static IEnumerable<MethodInfo> FindSimilarNamedMethods(Type type, string methodName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FindSimilarNamedMethods>d__14(-2) { <>3__type = type, <>3__methodName = methodName }; } private static MethodInfo FindMethodBySignatureShape(Type type, string originalName, Type[] parameterTypes) { MethodInfo[] methods; try { methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch { return null; } string target = originalName.ToLowerInvariant(); MethodInfo methodInfo = (from m in methods where ParametersMatchExactly(m, parameterTypes) orderby LevenshteinDistance(m.Name.ToLowerInvariant(), target) select m).FirstOrDefault(); if (methodInfo != null) { return methodInfo; } return (from m in methods where m.GetParameters().Length == parameterTypes.Length orderby LevenshteinDistance(m.Name.ToLowerInvariant(), target) select m).FirstOrDefault(); } private static bool ParametersMatchExactly(MethodBase m, Type[] parameterTypes) { ParameterInfo[] parameters = m.GetParameters(); if (parameters.Length != parameterTypes.Length) { return false; } for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType != parameterTypes[i]) { return false; } } return true; } private static int LevenshteinDistance(string a, string b) { if (string.IsNullOrEmpty(a)) { return b?.Length ?? 0; } if (string.IsNullOrEmpty(b)) { return a.Length; } int[,] array = new int[a.Length + 1, b.Length + 1]; for (int i = 0; i <= a.Length; i++) { array[i, 0] = i; } for (int j = 0; j <= b.Length; j++) { array[0, j] = j; } for (int k = 1; k <= a.Length; k++) { for (int l = 1; l <= b.Length; l++) { int num = ((a[k - 1] != b[l - 1]) ? 1 : 0); array[k, l] = Math.Min(Math.Min(array[k - 1, l] + 1, array[k, l - 1] + 1), array[k - 1, l - 1] + num); } } return array[a.Length, b.Length]; } } } namespace BlackBox.WubarrksEye.Core { internal static class ApiDumpWriter { [CompilerGenerated] private sealed class <GetInheritanceChain>d__2 : IEnumerable<Type>, IEnumerable, IEnumerator<Type>, IDisposable, IEnumerator { private int <>1__state; private Type <>2__current; private int <>l__initialThreadId; private Type t; public Type <>3__t; Type IEnumerator<Type>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetInheritanceChain>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; t = t.BaseType; break; } if (t != null) { <>2__current = t; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<Type> IEnumerable<Type>.GetEnumerator() { <GetInheritanceChain>d__2 <GetInheritanceChain>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <GetInheritanceChain>d__ = this; } else { <GetInheritanceChain>d__ = new <GetInheritanceChain>d__2(0); } <GetInheritanceChain>d__.t = <>3__t; return <GetInheritanceChain>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<Type>)this).GetEnumerator(); } } public static void WriteTypeApi(TextWriter w, Type type) { if (type == null) { return; } AssemblyName name = type.Assembly.GetName(); w.WriteLine("=== API BEGIN ==="); w.WriteLine("Type: " + type.FullName); w.WriteLine("Namespace: " + (type.Namespace ?? "<none>")); w.WriteLine("Assembly: " + name.Name); w.WriteLine($"AssemblyVersion: {name.Version}"); w.WriteLine("Kind: " + GetTypeKind(type)); w.WriteLine($"IsAbstract: {type.IsAbstract}"); w.WriteLine($"IsSealed: {type.IsSealed}"); w.WriteLine($"IsGenericType: {type.IsGenericType}"); Type[] array = (type.IsGenericType ? type.GetGenericArguments() : Type.EmptyTypes); w.WriteLine("GenericArguments:"); if (array.Length == 0) { w.WriteLine("<none>"); } else { Type[] array2 = array; foreach (Type type2 in array2) { w.WriteLine(type2.FullName ?? type2.Name); } } w.WriteLine("InheritanceChain:"); foreach (Type item in GetInheritanceChain(type)) { w.WriteLine(item.FullName ?? item.Name); } w.WriteLine("Implements:"); Type[] interfaces = type.GetInterfaces(); if (interfaces.Length == 0) { w.WriteLine("<none>"); } else { foreach (Type item2 in interfaces.OrderBy((Type i) => i.FullName)) { w.WriteLine(item2.FullName); } } w.WriteLine("Attributes:"); List<string> list = SafeGetCustomAttributes(type); if (list.Count == 0) { w.WriteLine("<none>"); } else { foreach (string item3 in list) { w.WriteLine(item3); } } w.WriteLine("EnumValues:"); if (type.IsEnum) { string[] names = Enum.GetNames(type); Array values = Enum.GetValues(type); for (int k = 0; k < names.Length; k++) { w.WriteLine($"{names[k]} = {(int)values.GetValue(k)}"); } } else { w.WriteLine("<none>"); } w.WriteLine("Fields:"); FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fields.Length == 0) { w.WriteLine("<none>"); } else { foreach (FieldInfo item4 in fields.OrderBy((FieldInfo f) => f.Name)) { w.WriteLine(item4.FieldType.FullName + " " + item4.Name + " " + GetFieldModifiers(item4)); } } w.WriteLine("Properties:"); PropertyInfo[] properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (properties.Length == 0) { w.WriteLine("<none>"); } else { foreach (PropertyInfo item5 in properties.OrderBy((PropertyInfo p) => p.Name)) { w.WriteLine(item5.PropertyType.FullName + " " + item5.Name + " " + GetPropertyModifiers(item5) + " " + GetPropertyAccessorFlags(item5)); } } w.WriteLine("Events:"); EventInfo[] events = type.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (events.Length == 0) { w.WriteLine("<none>"); } else { foreach (EventInfo item6 in events.OrderBy((EventInfo e) => e.Name)) { w.WriteLine(item6.EventHandlerType.FullName + " " + item6.Name + " " + GetMethodModifiers(item6.GetAddMethod(nonPublic: true))); } } w.WriteLine("Methods:"); MethodInfo[] array3 = (from m in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where !m.IsSpecialName orderby m.Name, m.GetParameters().Length select m).ToArray(); if (array3.Length == 0) { w.WriteLine("<none>"); } else { MethodInfo[] array4 = array3; foreach (MethodInfo m2 in array4) { w.WriteLine(FormatFullMethodSignature(m2)); } } w.WriteLine("UnityMetadata:"); w.WriteLine($"IsMonoBehaviour: {typeof(MonoBehaviour).IsAssignableFrom(type)}"); w.WriteLine($"IsScriptableObject: {typeof(ScriptableObject).IsAssignableFrom(type)}"); w.WriteLine("RequiredComponents:"); RequireComponent[] array5 = type.GetCustomAttributes(inherit: true).OfType<RequireComponent>().ToArray(); if (array5.Length == 0) { w.WriteLine("<none>"); } else { RequireComponent[] array6 = array5; foreach (RequireComponent val in array6) { if (val.m_Type0 != null) { w.WriteLine(val.m_Type0.FullName); } if (val.m_Type1 != null) { w.WriteLine(val.m_Type1.FullName); } if (val.m_Type2 != null) { w.WriteLine(val.m_Type2.FullName); } } } w.WriteLine("=== API END ==="); } private static string GetTypeKind(Type t) { if (t.IsInterface) { return "interface"; } if (t.IsEnum) { return "enum"; } if (t.IsValueType) { return "struct"; } return "class"; } [IteratorStateMachine(typeof(<GetInheritanceChain>d__2))] private static IEnumerable<Type> GetInheritanceChain(Type t) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetInheritanceChain>d__2(-2) { <>3__t = t }; } private static List<string> SafeGetCustomAttributes(MemberInfo m) { try { return (from a in m.GetCustomAttributes(inherit: true) select a.GetType().FullName).ToList(); } catch { return new List<string>(); } } private static string GetFieldModifiers(FieldInfo f) { List<string> list = new List<string>(); list.Add("[" + (f.IsPublic ? "public" : (f.IsFamily ? "protected" : (f.IsAssembly ? "internal" : (f.IsPrivate ? "private" : "unknown"))))); if (f.IsStatic) { list.Add("static"); } if (f.IsInitOnly) { list.Add("readonly"); } if (f.IsLiteral && !f.IsInitOnly) { list.Add("const"); } list.Add("]"); return string.Join(" ", list); } private static string GetPropertyModifiers(PropertyInfo p) { MethodInfo methodInfo = p.GetGetMethod(nonPublic: true) ?? p.GetSetMethod(nonPublic: true); if (!(methodInfo != null)) { return ""; } return GetMethodModifiers(methodInfo); } private static string GetPropertyAccessorFlags(PropertyInfo p) { MethodInfo getMethod = p.GetGetMethod(nonPublic: true); MethodInfo setMethod = p.GetSetMethod(nonPublic: true); if (getMethod == null && setMethod == null) { return ""; } List<string> list = new List<string>(); if (getMethod != null) { list.Add(GetVisibility(getMethod) + " get"); } if (setMethod != null) { list.Add(GetVisibility(setMethod) + " set"); } return "{" + string.Join(", ", list) + "}"; } private static string GetVisibility(MethodBase m) { if (m.IsPublic) { return "public"; } if (m.IsFamily) { return "protected"; } if (m.IsAssembly) { return "internal"; } if (m.IsPrivate) { return "private"; } return "unknown"; } private static string GetMethodModifiers(MethodBase m) { List<string> list = new List<string>(); list.Add("[" + GetVisibility(m)); if (m.IsStatic) { list.Add("static"); } if (m is MethodInfo methodInfo) { if (methodInfo.IsAbstract) { list.Add("abstract"); } else if (methodInfo.IsVirtual && methodInfo.GetBaseDefinition() != methodInfo && !methodInfo.IsFinal) { list.Add("override"); } else if (methodInfo.IsVirtual && !methodInfo.IsAbstract && !methodInfo.IsFinal) { list.Add("virtual"); } } list.Add("]"); return string.Join(" ", list); } private static string FormatFullMethodSignature(MethodInfo m) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(GetMethodModifiers(m)); stringBuilder.Append(' '); stringBuilder.Append(m.ReturnType.FullName); stringBuilder.Append(' '); stringBuilder.Append(m.Name); if (m.IsGenericMethod) { Type[] genericArguments = m.GetGenericArguments(); stringBuilder.Append('<'); stringBuilder.Append(string.Join(", ", genericArguments.Select((Type a) => a.FullName ?? a.Name))); stringBuilder.Append('>'); } stringBuilder.Append('('); ParameterInfo[] parameters = m.GetParameters(); for (int i = 0; i < parameters.Length; i++) { if (i > 0) { stringBuilder.Append(", "); } ParameterInfo parameterInfo = parameters[i]; if (parameterInfo.IsOut) { stringBuilder.Append("out "); } else if (parameterInfo.ParameterType.IsByRef) { stringBuilder.Append("ref "); } stringBuilder.Append(parameterInfo.ParameterType.FullName ?? parameterInfo.ParameterType.Name); stringBuilder.Append(' '); stringBuilder.Append(parameterInfo.Name); } stringBuilder.Append(')'); return stringBuilder.ToString(); } } internal static class BlackBoxConfig { public static ConfigEntry<bool> EnableMod; public static ConfigEntry<string> PhysicsAuthorityMode; public static ConfigEntry<bool> EnableLedger; public static ConfigEntry<bool> EnableCodex; public static ConfigEntry<bool> EnablePromotions; public static ConfigEntry<int> LedgerMaxSizeMB; public static ConfigEntry<int> CodexMaxSizeMB; public static ConfigEntry<int> EyeDumpMaxFileSizeKB; public static ConfigEntry<int> EyeDumpMaxFileSizeExpertKB; public static ConfigEntry<bool> DeepDiagnostics; public static ConfigEntry<bool> LedgerDebug; public static ConfigEntry<bool> CodexDebug; public static ConfigEntry<bool> DumpAllFields; public static ConfigEntry<bool> DumpAllMethods; public static ConfigEntry<bool> DumpAllProperties; public static ConfigEntry<bool> DumpAllComponents; public static ConfigEntry<bool> EnableExpertMode; public static ConfigEntry<bool> DumpAllFieldsExpert; public static ConfigEntry<bool> DumpAllComponentsExpert; public static ConfigEntry<bool> DumpAllMethodsExpert; public static ConfigEntry<bool> DumpAllPropertiesExpert; public static void Bind(ConfigFile Config) { EnableMod = Config.Bind<bool>("Core", "EnableMod", true, "Turns the mod on or off. Leave this on unless you're troubleshooting."); PhysicsAuthorityMode = Config.Bind<string>("Core", "PhysicsAuthorityMode", "server", "Who controls physics: the server or the client. If you don't know, leave it alone."); EnableLedger = Config.Bind<bool>("Core", "EnableLedger", true, "Turns on the Ledger system (records game data). Safe for all users."); EnableCodex = Config.Bind<bool>("Core", "EnableCodex", true, "Turns on the Codex system (stores patch info). Safe for all users."); EnablePromotions = Config.Bind<bool>("Core", "EnablePromotions", true, "Allows the Eye to promote changes into the Codex. Safe unless you're debugging."); LedgerMaxSizeMB = Config.Bind<int>("Storage", "LedgerMaxSizeMB", 64, "How big the Ledger is allowed to get. Normal use: 5–20 MB. Heavy use: 20–60 MB. Extreme use: 100–300 MB. Expert dumps can push it higher. Default is safe."); CodexMaxSizeMB = Config.Bind<int>("Storage", "CodexMaxSizeMB", 32, "How big the Codex is allowed to get. Usually stays under 1 MB. Even heavy use rarely exceeds 3 MB. Default is more than enough."); EyeDumpMaxFileSizeKB = Config.Bind<int>("Storage", "EyeDumpMaxFileSizeKB", 5120, "Maximum size of normal dump files. Typical dumps: 200 KB – 3 MB. Prevents runaway file growth."); EyeDumpMaxFileSizeExpertKB = Config.Bind<int>("Storage", "EyeDumpMaxFileSizeExpertKB", 20480, "Maximum size of expert dumps. Expert dumps can reach 20–80 MB depending on settings. Do not raise above 100 MB unless you know what you're doing."); DeepDiagnostics = Config.Bind<bool>("Diagnostics", "DeepDiagnostics", false, "Extra logging and extra detail. Helps debugging. Slows things down."); LedgerDebug = Config.Bind<bool>("Diagnostics", "LedgerDebug", false, "Shows Ledger internals in the log. Only useful for developers."); CodexDebug = Config.Bind<bool>("Diagnostics", "CodexDebug", false, "Shows Codex internals in the log. Only useful for developers."); DumpAllFields = Config.Bind<bool>("Dumping", "DumpAllFields", false, "Shows more info about objects. Adds ~200–800 KB per dump."); DumpAllMethods = Config.Bind<bool>("Dumping", "DumpAllMethods", false, "Lists all functions on objects. Adds ~100–300 KB."); DumpAllProperties = Config.Bind<bool>("Dumping", "DumpAllProperties", false, "Lists all properties on objects. Adds ~200–500 KB."); DumpAllComponents = Config.Bind<bool>("Dumping", "DumpAllComponents", false, "Shows all components attached to objects. Adds 1–3 MB depending on scene complexity."); EnableExpertMode = Config.Bind<bool>("Expert", "EnableExpertMode", false, "Unlocks dangerous settings. Expert dumps can reach 20–200 MB. If you don't know what this means, don't touch it."); DumpAllFieldsExpert = Config.Bind<bool>("Expert", "DumpAllFieldsExpert", false, "Shows *every* value inside objects, even hidden ones. Adds 5–20 MB per dump. Slow."); DumpAllComponentsExpert = Config.Bind<bool>("Expert", "DumpAllComponentsExpert", false, "Shows *every* Unity component, even engine internals. Adds 20–80 MB per dump. Very slow."); DumpAllMethodsExpert = Config.Bind<bool>("Expert", "DumpAllMethodsExpert", false, "Lists every function, including hidden ones. Adds 1–5 MB."); DumpAllPropertiesExpert = Config.Bind<bool>("Expert", "DumpAllPropertiesExpert", false, "Lists every property, including hidden ones. Adds 1–5 MB."); } } internal static class BlackBoxLogger { private static ManualLogSource _log; internal static void Initialize(ManualLogSource log) { _log = log; } private static string Colorize(string message) { try { if (message.Contains("[Codex]")) { return "<color=#FF00FF>" + message + "</color>"; } if (message.Contains("[Diagnostics]") || message.Contains("dump_eye")) { return "<color=#00FFFF>" + message + "</color>"; } if (message.Contains("[Stable]") || message.Contains("[Adaptive]")) { return "<color=#00FF00>" + message + "</color>"; } if (message.Contains("[NeedsAttention]") || message.Contains("[Drift]")) { return "<color=#FFFF00>" + message + "</color>"; } if (message.Contains("[Failure]") || message.Contains("[Watchdog]") || message.Contains("[Unstable]") || message.Contains("[Oscillating]")) { return "<color=#FF0000>" + message + "</color>"; } return message; } catch { return message; } } internal static void Info(string message) { try { ManualLogSource log = _log; if (log != null) { log.LogInfo((object)Colorize("[BlackBox] " + message)); } } catch { } } internal static void Warn(string message) { try { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)Colorize("[BlackBox] " + message)); } } catch { } } internal static void Error(string message) { try { ManualLogSource log = _log; if (log != null) { log.LogError((object)Colorize("[BlackBox] " + message)); } } catch { } } internal static void MaskedError(string message) { try { ManualLogSource log = _log; if (log != null) { log.LogError((object)Colorize("[BlackBox] " + message)); } } catch { } } } internal static class BootSplash { private static ManualLogSource _logger; public static void Initialize(ManualLogSource logger) { _logger = logger ?? throw new ArgumentNullException("logger"); } public static void Render(HarmonyIntelligence.HarmonyTelemetry harmony, LedgerSnapshot ledger, CodexSnapshot codex, DumpSnapshot dump) { if (_logger == null) { throw new InvalidOperationException("BootSplash.Initialize must be called before Render."); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("┌──────────────────────────────────────────────────────────────┐"); stringBuilder.AppendLine("│ W U B A R R K ’ S E Y E │"); stringBuilder.AppendLine("│ THE EYE IS OPEN │"); stringBuilder.AppendLine("├──────────────────────────────────────────────────────────────┤"); stringBuilder.AppendLine($"│ Mod Enabled: {BlackBoxConfig.EnableMod.Value}"); stringBuilder.AppendLine("│ Physics Authority Mode: " + BlackBoxConfig.PhysicsAuthorityMode.Value); stringBuilder.AppendLine($"│ Expert Mode: {BlackBoxConfig.EnableExpertMode.Value}"); stringBuilder.AppendLine("├──────────────────────────────────────────────────────────────┤"); stringBuilder.AppendLine("│ Harmony Patching: │"); stringBuilder.AppendLine($"│ Patch Classes Found: {harmony?.PatchClassesFound ?? 0}"); stringBuilder.AppendLine($"│ Target Methods Matched: {harmony?.TargetMethodsMatched ?? 0}"); stringBuilder.AppendLine($"│ Patches Applied: {harmony?.PatchesApplied ?? 0}"); stringBuilder.AppendLine("├──────────────────────────────────────────────────────────────┤"); stringBuilder.AppendLine($"│ Ledger: {BlackBoxConfig.EnableLedger.Value}"); stringBuilder.AppendLine($"│ Ledger Size: {ledger.CurrentSizeMB} / {BlackBoxConfig.LedgerMaxSizeMB.Value} MB"); stringBuilder.AppendLine($"│ Ledger Debug: {BlackBoxConfig.LedgerDebug.Value}"); stringBuilder.AppendLine($"│ Evidence Files: {ledger.EvidenceCount}"); stringBuilder.AppendLine($"│ Aggregates: {ledger.AggregateCount}"); stringBuilder.AppendLine("│ Last Ingestion: " + ledger.LastIngestionTimestamp); stringBuilder.AppendLine("├──────────────────────────────────────────────────────────────┤"); stringBuilder.AppendLine($"│ Codex: {BlackBoxConfig.EnableCodex.Value}"); stringBuilder.AppendLine($"│ Promotions Enabled: {BlackBoxConfig.EnablePromotions.Value}"); stringBuilder.AppendLine($"│ Codex Size: {codex.CurrentSizeMB} / {BlackBoxConfig.CodexMaxSizeMB.Value} MB"); stringBuilder.AppendLine($"│ Codex Debug: {BlackBoxConfig.CodexDebug.Value}"); stringBuilder.AppendLine("│ Last Promotion: " + codex.LastPromotionTimestamp); stringBuilder.AppendLine("├──────────────────────────────────────────────────────────────┤"); stringBuilder.AppendLine("│ Eye Dump System: │"); stringBuilder.AppendLine($"│ Deep Diagnostics: {BlackBoxConfig.DeepDiagnostics.Value}"); stringBuilder.AppendLine($"│ Dump Flags: Fields={BlackBoxConfig.DumpAllFields.Value}, Methods={BlackBoxConfig.DumpAllMethods.Value}"); stringBuilder.AppendLine($"│ Props={BlackBoxConfig.DumpAllProperties.Value}, Comps={BlackBoxConfig.DumpAllComponents.Value}"); stringBuilder.AppendLine($"│ File Size Limit: {BlackBoxConfig.EyeDumpMaxFileSizeKB.Value} KB"); stringBuilder.AppendLine($"│ Expert Override: {BlackBoxConfig.EyeDumpMaxFileSizeExpertKB.Value} KB"); stringBuilder.AppendLine("│ Last Dump: " + dump.LastDumpTimestamp); stringBuilder.AppendLine("├──────────────────────────────────────────────────────────────┤"); stringBuilder.AppendLine("│ Status: All Systems Online │"); stringBuilder.AppendLine("│ The Eye is Open │"); stringBuilder.AppendLine("└──────────────────────────────────────────────────────────────┘"); _logger.LogInfo((object)stringBuilder.ToString()); } } public sealed class CodexRuntime { private readonly string _codexRootPath; private readonly int _maxSizeMB; private CodexSnapshot _lastSnapshot = CodexSnapshot.Empty(); public CodexSnapshot LastSnapshot => _lastSnapshot; public CodexRuntime(string codexRootPath, int maxSizeMB) { if (string.IsNullOrWhiteSpace(codexRootPath)) { throw new ArgumentException("Codex root path must not be null or empty.", "codexRootPath"); } _codexRootPath = codexRootPath; _maxSizeMB = ((maxSizeMB > 0) ? maxSizeMB : 0); Directory.CreateDirectory(_codexRootPath); } public CodexSnapshot BuildSnapshot(string lastPromotionTimestamp = null) { long num = 0L; if (Directory.Exists(_codexRootPath)) { string[] files = Directory.GetFiles(_codexRootPath, "*", SearchOption.AllDirectories); foreach (string fileName in files) { try { FileInfo fileInfo = new FileInfo(fileName); num += fileInfo.Length; } catch { } } } return _lastSnapshot = new CodexSnapshot((int)(num / 1048576), lastPromotionTimestamp ?? _lastSnapshot.LastPromotionTimestamp); } public bool IsAtOrAboveMaxSize() { if (_maxSizeMB <= 0) { return false; } return _lastSnapshot.CurrentSizeMB >= _maxSizeMB; } public void UpdateLastPromotionTimestamp(string timestamp) { string lastPromotionTimestamp = (string.IsNullOrWhiteSpace(timestamp) ? "n/a" : timestamp); _lastSnapshot = new CodexSnapshot(_lastSnapshot.CurrentSizeMB, lastPromotionTimestamp); } } internal static class DumpMLBuilder { private const string MlFileName = "dumpML.json"; public static void BuildAndWriteDump(ManualLogSource logger, string dumpRootPath, LedgerSnapshot ledgerSnapshot, DumpSnapshot dumpSnapshot, int codexMaxSizeMB = 0) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown if (logger == null) { throw new ArgumentNullException("logger"); } if (string.IsNullOrWhiteSpace(dumpRootPath)) { throw new ArgumentException("Dump root path must not be null or empty.", "dumpRootPath"); } try { Directory.CreateDirectory(dumpRootPath); } catch (Exception arg) { logger.LogError((object)$"[Eye/DumpML] Failed to ensure dump root directory '{dumpRootPath}': {arg}"); return; } try { logger.LogInfo((object)("[Eye/DumpML] Building Fort-Knox ML dump for '" + dumpRootPath + "' ...")); CodexSnapshot snapshot = BuildCodexSnapshotSafe(logger, codexMaxSizeMB); JObject val = new JObject { ["meta"] = (JToken)(object)BuildMetaSection(dumpRootPath), ["ledger"] = (JToken)(object)BuildLedgerSection(ledgerSnapshot), ["codex"] = (JToken)(object)BuildCodexSection(snapshot), ["dumpRuntime"] = (JToken)(object)BuildDumpRuntimeSection(dumpSnapshot), ["deep"] = (JToken)(object)BuildDeepSection(logger, dumpRootPath) }; string text = Path.Combine(dumpRootPath, "dumpML.json"); File.WriteAllText(text, ((JToken)val).ToString((Formatting)1)); logger.LogInfo((object)("[Eye/DumpML] Fort-Knox ML dump written to '" + text + "'.")); } catch (Exception arg2) { logger.LogError((object)$"[Eye/DumpML] Failed to build ML dump for '{dumpRootPath}': {arg2}"); } } private static JObject BuildMetaSection(string dumpRootPath) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown return new JObject { ["timestampUtc"] = JToken.op_Implicit(DateTime.UtcNow.ToString("u")), ["dumpRoot"] = JToken.op_Implicit(dumpRootPath) }; } private static JObject BuildLedgerSection(LedgerSnapshot snapshot) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown if (snapshot == null) { snapshot = LedgerSnapshot.Empty(); } return new JObject { ["currentSizeMB"] = JToken.op_Implicit(snapshot.CurrentSizeMB), ["evidenceCount"] = JToken.op_Implicit(snapshot.EvidenceCount), ["aggregateCount"] = JToken.op_Implicit(snapshot.AggregateCount), ["lastIngestionTimestamp"] = JToken.op_Implicit(snapshot.LastIngestionTimestamp ?? "n/a") }; } private static JObject BuildCodexSection(CodexSnapshot snapshot) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown if (snapshot == null) { snapshot = CodexSnapshot.Empty(); } return new JObject { ["currentSizeMB"] = JToken.op_Implicit(snapshot.CurrentSizeMB), ["lastPromotionTimestamp"] = JToken.op_Implicit(snapshot.LastPromotionTimestamp ?? "n/a") }; } private static JObject BuildDumpRuntimeSection(DumpSnapshot snapshot) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown if (snapshot == null) { snapshot = DumpSnapshot.Empty(); } return new JObject { ["lastDumpTimestamp"] = JToken.op_Implicit(snapshot.LastDumpTimestamp ?? "n/a") }; } private static JObject BuildDeepSection(ManualLogSource logger, string dumpRootPath) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown JObject val = new JObject(); AddRawTextIfExists(logger, val, dumpRootPath, "dump_meta", "dump_meta.txt"); AddRawTextIfExists(logger, val, dumpRootPath, "eye_dump", "eye_dump.txt"); AddJsonLinesIfExists(logger, val, dumpRootPath, "harmony_evidence", "harmony_evidence.jsonl"); return val; } private static void AddRawTextIfExists(ManualLogSource logger, JObject target, string dumpRootPath, string logicalKey, string fileName) { try { string path = Path.Combine(dumpRootPath, fileName); if (File.Exists(path)) { string text = File.ReadAllText(path); target[logicalKey] = JToken.op_Implicit(text); } } catch (Exception ex) { if (logger != null) { logger.LogWarning((object)("[Eye/DumpML] Failed to read raw text '" + fileName + "' for key '" + logicalKey + "': " + ex.Message)); } } } private static void AddJsonLinesIfExists(ManualLogSource logger, JObject target, string dumpRootPath, string logicalKey, string fileName) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown try { string path = Path.Combine(dumpRootPath, fileName); if (!File.Exists(path)) { return; } JArray val = new JArray(); foreach (string item in File.ReadLines(path)) { if (!string.IsNullOrWhiteSpace(item)) { try { val.Add(JToken.Parse(item)); } catch { val.Add(JToken.op_Implicit(item)); } } } target[logicalKey] = (JToken)(object)val; } catch (Exception ex) { if (logger != null) { logger.LogWarning((object)("[Eye/DumpML] Failed to read JSONL '" + fileName + "' for key '" + logicalKey + "': " + ex.Message)); } } } private static CodexSnapshot BuildCodexSnapshotSafe(ManualLogSource logger, int codexMaxSizeMB) { try { return new CodexRuntime(Path.Combine(Paths.ConfigPath, "WubarrksEye", "Codex"), codexMaxSizeMB).BuildSnapshot() ?? CodexSnapshot.Empty(); } catch (Exception ex) { if (logger != null) { logger.LogWarning((object)("[Eye/DumpML] Failed to build Codex snapshot: " + ex.Message)); } return CodexSnapshot.Empty(); } } } internal static class DumpRuntime { private static ManualLogSource _logger; private static readonly string DumpRootPath = Path.Combine(Paths.ConfigPath, "WubarrksEye", "Dumps"); private static readonly string MetaFilePath = Path.Combine(DumpRootPath, "dump_meta.txt"); public static void Initialize(ManualLogSource logger) { _logger = logger ?? throw new ArgumentNullException("logger"); EnsureDirectory(); _logger.LogInfo((object)"[Eye/Dump] DumpRuntime initialized."); } public static DumpSnapshot BuildSnapshot() { try { EnsureDirectory(); return new DumpSnapshot(ReadMetaTimestampSafe(MetaFilePath)); } catch (Exception arg) { ManualLogSource logger = _logger; if (logger != null) { logger.LogError((object)$"[Eye/Dump] Failed to build DumpSnapshot: {arg}"); } return DumpSnapshot.Empty(); } } public static void UpdateLastDumpTimestamp(DateTime utcNow) { try { EnsureDirectory(); File.WriteAllText(MetaFilePath, utcNow.ToString("u")); } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Dump] Failed to write dump meta file '" + MetaFilePath + "': " + ex.Message)); } } } private static void EnsureDirectory() { try { if (!Directory.Exists(DumpRootPath)) { Directory.CreateDirectory(DumpRootPath); } } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Dump] Failed to create directory '" + DumpRootPath + "': " + ex.Message)); } } } private static string ReadMetaTimestampSafe(string metaFile) { try { if (!File.Exists(metaFile)) { return "n/a"; } string text = File.ReadAllText(metaFile).Trim(); if (string.IsNullOrEmpty(text)) { return "n/a"; } return text; } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Dump] Failed to read dump meta file '" + metaFile + "': " + ex.Message)); } return "n/a"; } } } internal static class DumpUtils { public static string CreateNewDumpRoot() { string text = Path.Combine(Paths.ConfigPath, "WubarrksEye", "Dumps"); Directory.CreateDirectory(text); string path = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); string text2 = Path.Combine(text, path); Directory.CreateDirectory(text2); BlackBoxLogger.Info("[Eye] Created new dump directory: " + text2); return text2; } public static void SafeCall(string label, string dumpRoot, Action action) { try { BlackBoxLogger.Info("[Eye] Dumping " + label + "..."); action(); BlackBoxLogger.Info("[Eye] " + label + " dump complete."); } catch (Exception ex) { BlackBoxLogger.Warn("[Eye] " + label + " dump failed: " + ex.Message); WriteTextFile(dumpRoot, label + "_ERROR.txt", "Subsystem '" + label + "' failed:\n" + ex.Message); } } public static void WriteTextFile(string folder, string fileName, string content) { try { Directory.CreateDirectory(folder); string path = Path.Combine(folder, fileName); int num = (BlackBoxConfig.EnableExpertMode.Value ? BlackBoxConfig.EyeDumpMaxFileSizeExpertKB.Value : BlackBoxConfig.EyeDumpMaxFileSizeKB.Value); int num2 = num * 1024; byte[] bytes = Encoding.UTF8.GetBytes(content); if (bytes.Length > num2) { BlackBoxLogger.Warn($"[Eye] File '{fileName}' exceeded size limit ({num} KB). Truncating."); byte[] array = new byte[num2]; Array.Copy(bytes, array, num2); File.WriteAllBytes(path, array); } else { File.WriteAllBytes(path, bytes); } } catch (Exception ex) { BlackBoxLogger.Error("[Eye] Failed to write file '" + fileName + "': " + ex.Message); } } public static string EnsureSubfolder(string root, string name) { string text = Path.Combine(root, name); Directory.CreateDirectory(text); return text; } } internal static class EyeCommands { private static ManualLogSource _logger; public static void Initialize(ManualLogSource logger) { _logger = logger ?? throw new ArgumentNullException("logger"); RegisterCommand("dump_eye", DumpEye); RegisterCommand("dump_eye_deep", DumpEyeDeep); RegisterCommand("dump_eye_target", DumpEyeTarget); RegisterCommand("dump_eye_api_all", DumpEyeApiAll); _logger.LogInfo((object)"[Eye/Commands] EyeCommands initialized."); } private static void RegisterCommand(string name, Action<string[]> handler) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) try { new ConsoleCommand(name, "Wubarrk's Eye: " + name, (ConsoleEvent)delegate(ConsoleEventArgs args) { handler(args.Args); }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); _logger.LogInfo((object)("[Eye/Commands] Registered command: " + name)); } catch (Exception arg) { _logger.LogError((object)$"[Eye/Commands] Failed to register command '{name}': {arg}"); } } private static void DumpEye(string[] args) { try { _logger.LogInfo((object)"[Eye/Commands] dump_eye invoked."); EyeDumpSystem.Run(Path.Combine(Paths.ConfigPath, "WubarrksEye", "Dumps"), new string[1] { "basic" }); } catch (Exception arg) { _logger.LogError((object)$"[Eye/Commands] dump_eye failed: {arg}"); } } private static void DumpEyeTarget(string[] args) { try { if (!BlackBoxConfig.EnableExpertMode.Value) { _logger.LogWarning((object)"[Eye/Commands] dump_eye_target requires Expert Mode."); return; } if (args == null || args.Length == 0) { _logger.LogWarning((object)"[Eye/Commands] dump_eye_target requires a target name."); return; } string text = args[0]; _logger.LogInfo((object)("[Eye/Commands] dump_eye_target invoked for: " + text)); EyeDumpSystem.Run(Path.Combine(Paths.ConfigPath, "WubarrksEye", "Dumps"), new string[1] { "deep" }); AppendTargetToLatestDump(text); } catch (Exception arg) { _logger.LogError((object)$"[Eye/Commands] dump_eye_target failed: {arg}"); } } private static void AppendTargetToLatestDump(string target) { try { string path = Path.Combine(Paths.ConfigPath, "WubarrksEye", "Dumps"); string path2 = Path.Combine(path, "dump_id.txt"); if (!File.Exists(path2)) { _logger.LogWarning((object)"[Eye/Commands] No dump_id.txt found; cannot append target."); return; } if (!int.TryParse(File.ReadAllText(path2).Trim(), out var result)) { _logger.LogWarning((object)"[Eye/Commands] Invalid dump_id.txt; cannot append target."); return; } int num = result - 1; string path3 = Path.Combine(Path.Combine(path, $"Dump_{num:D4}"), "dump_meta.txt"); if (!File.Exists(path3)) { _logger.LogWarning((object)"[Eye/Commands] No dump_meta.txt found; cannot append target."); return; } File.AppendAllText(path3, "\nTarget=" + target); _logger.LogInfo((object)$"[Eye/Commands] Target '{target}' appended to dump {num}."); } catch (Exception ex) { _logger.LogWarning((object)("[Eye/Commands] Failed to append target: " + ex.Message)); } } private static void DumpEyeDeep(string[] args) { try { if (!BlackBoxConfig.EnableExpertMode.Value) { _logger.LogWarning((object)"[Eye/Commands] dump_eye_deep requires Expert Mode."); return; } _logger.LogInfo((object)"[Eye/Commands] dump_eye_deep invoked."); EyeDumpSystem.Run(Path.Combine(Paths.ConfigPath, "WubarrksEye", "Dumps"), new string[1] { "deep" }); } catch (Exception arg) { _logger.LogError((object)$"[Eye/Commands] dump_eye_deep failed: {arg}"); } } private static void DumpEyeApiAll(string[] args) { try { if (!BlackBoxConfig.EnableExpertMode.Value) { _logger.LogWarning((object)"[Eye/Commands] dump_eye_api_all requires Expert Mode."); return; } _logger.LogInfo((object)"[Eye/Commands] dump_eye_api_all invoked."); string text = Path.Combine(Paths.ConfigPath, "WubarrksEye", "Dumps"); Directory.CreateDirectory(text); DumpApiAll.RunApiAll(text); _logger.LogInfo((object)"[Eye/Commands] dump_eye_api_all completed."); } catch (Exception arg) { _logger.LogError((object)$"[Eye/Commands] dump_eye_api_all failed: {arg}"); } } } internal static class EyeDumpNotifier { private static ManualLogSource _logger; private static AbyssalLedgerRuntime _ledgerRuntime; public static void Initialize(ManualLogSource logger, AbyssalLedgerRuntime ledgerRuntime) { _logger = logger ?? throw new ArgumentNullException("logger"); _ledgerRuntime = ledgerRuntime ?? throw new ArgumentNullException("ledgerRuntime"); _logger.LogInfo((object)"[Eye/Notifier] EyeDumpNotifier initialized."); } public static void NotifyDumpCreated(int dumpId, string dumpFolderPath) { if (dumpId <= 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)$"[Eye/Notifier] NotifyDumpCreated called with invalid dumpId={dumpId}. Ignoring."); } return; } if (string.IsNullOrEmpty(dumpFolderPath)) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)$"[Eye/Notifier] NotifyDumpCreated called with null/empty dumpFolderPath for dumpId={dumpId}. Ignoring."); } return; } try { DateTime utcNow = DateTime.UtcNow; DumpRuntime.UpdateLastDumpTimestamp(utcNow); _ledgerRuntime.IngestDump(dumpId, dumpFolderPath); LedgerRuntime.UpdateLastIngestionTimestamp(utcNow); CodexBootstrapper.RefreshSnapshot(); ManualLogSource logger3 = _logger; if (logger3 != null) { logger3.LogInfo((object)$"[Eye/Notifier] Dump {dumpId} ingested and Codex snapshot refreshed successfully."); } } catch (Exception arg) { ManualLogSource logger4 = _logger; if (logger4 != null) { logger4.LogError((object)$"[Eye/Notifier] NotifyDumpCreated failed for dumpId={dumpId}: {arg}"); } } } } internal static class EyeDumpSystem { public static void Run(string dumpRoot, string[] args) { try { if (args.Length == 0) { BlackBoxLogger.Info("Usage: dump_eye <basic|runtime|api|deep>"); return; } string text = args[0].ToLowerInvariant(); switch (text) { case "basic": DumpBasic(dumpRoot); break; case "runtime": DumpRuntime(dumpRoot); break; case "api": DumpApi(dumpRoot); break; case "deep": DumpItDeep.RunDeep(dumpRoot, args); break; default: BlackBoxLogger.Warn("Unknown dump mode: " + text); break; } } catch (Exception arg) { BlackBoxLogger.Error($"[EyeDumpSystem] Dump failed: {arg}"); } } private static void DumpBasic(string dumpRoot) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) try { using StreamWriter streamWriter = new StreamWriter(Path.Combine(dumpRoot, "BasicDump.txt"), append: false); streamWriter.WriteLine("=== BASIC DUMP ==="); streamWriter.WriteLine("Unity Version: " + Application.unityVersion); streamWriter.WriteLine($"Platform: {Application.platform}"); streamWriter.WriteLine("Product: " + Application.productName); streamWriter.WriteLine("Company: " + Application.companyName); streamWriter.WriteLine("Version: " + Application.version); streamWriter.WriteLine("=================="); BlackBoxLogger.Info("[EyeDumpSystem] Basic dump complete."); } catch (Exception arg) { BlackBoxLogger.Error($"[EyeDumpSystem] Basic dump failed: {arg}"); } } private static void DumpRuntime(string dumpRoot) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) try { using StreamWriter streamWriter = new StreamWriter(Path.Combine(dumpRoot, "RuntimeDump.txt"), append: false); streamWriter.WriteLine("=== RUNTIME DUMP ==="); streamWriter.WriteLine($"Time: {DateTime.Now}"); Scene activeScene = SceneManager.GetActiveScene(); streamWriter.WriteLine("Scene: " + ((Scene)(ref activeScene)).name); streamWriter.WriteLine("===================="); BlackBoxLogger.Info("[EyeDumpSystem] Runtime dump complete."); } catch (Exception arg) { BlackBoxLogger.Error($"[EyeDumpSystem] Runtime dump failed: {arg}"); } } private static void DumpApi(string dumpRoot) { try { using StreamWriter streamWriter = new StreamWriter(Path.Combine(dumpRoot, "ApiDump.txt"), append: false); streamWriter.WriteLine("=== API DUMP ==="); streamWriter.WriteLine("This mode is deprecated. Use: dump_eye deep"); streamWriter.WriteLine("================"); BlackBoxLogger.Info("[EyeDumpSystem] API dump complete."); } catch (Exception arg) { BlackBoxLogger.Error($"[EyeDumpSystem] API dump failed: {arg}"); } } } internal static class FieldMapCache { private static readonly Dictionary<Type, List<FieldInfo>> _fieldCache = new Dictionary<Type, List<FieldInfo>>(); private static readonly Dictionary<Type, List<PropertyInfo>> _propertyCache = new Dictionary<Type, List<PropertyInfo>>(); private static readonly Dictionary<Type, List<MethodInfo>> _methodCache = new Dictionary<Type, List<MethodInfo>>(); internal static List<FieldInfo> GetFields(Type t) { if (t == null) { return new List<FieldInfo>(); } if (_fieldCache.TryGetValue(t, out List<FieldInfo> value)) { return value; } List<FieldInfo> list = SafeBuildFieldList(t); _fieldCache[t] = list; return list; } internal static List<PropertyInfo> GetProperties(Type t) { if (t == null) { return new List<PropertyInfo>(); } if (_propertyCache.TryGetValue(t, out List<PropertyInfo> value)) { return value; } List<PropertyInfo> list = SafeBuildPropertyList(t); _propertyCache[t] = list; return list; } internal static List<MethodInfo> GetMethods(Type t) { if (t == null) { return new List<MethodInfo>(); } if (_methodCache.TryGetValue(t, out List<MethodInfo> value)) { return value; } List<MethodInfo> list = SafeBuildMethodList(t); _methodCache[t] = list; return list; } private static List<FieldInfo> SafeBuildFieldList(Type t) { try { return new List<FieldInfo>(t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); } catch { return new List<FieldInfo>(); } } private static List<PropertyInfo> SafeBuildPropertyList(Type t) { try { return new List<PropertyInfo>(t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); } catch { return new List<PropertyInfo>(); } } private static List<MethodInfo> SafeBuildMethodList(Type t) { try { return new List<MethodInfo>(t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); } catch { return new List<MethodInfo>(); } } } internal static class HarmonyEvidenceIngestor { private static ManualLogSource _logger; public static void Initialize(ManualLogSource logger) { _logger = logger ?? throw new ArgumentNullException("logger"); _logger.LogInfo((object)"[Eye/HarmonyEvidence] HarmonyEvidenceIngestor initialized."); } public static void WriteHarmonyEvidence(int dumpId, string dumpFolderPath) { if (dumpId <= 0) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)$"[Eye/HarmonyEvidence] WriteHarmonyEvidence called with invalid dumpId={dumpId}. Ignoring."); } return; } if (string.IsNullOrEmpty(dumpFolderPath)) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)$"[Eye/HarmonyEvidence] WriteHarmonyEvidence called with null/empty dumpFolderPath for dumpId={dumpId}. Ignoring."); } return; } try { HarmonyIntelligence.HarmonyTelemetry lastSnapshot = HarmonyIntelligence.GetLastSnapshot(); if (lastSnapshot == null) { ManualLogSource logger3 = _logger; if (logger3 != null) { logger3.LogWarning((object)"[Eye/HarmonyEvidence] No Harmony telemetry available; skipping Harmony evidence."); } return; } using (StreamWriter streamWriter = new StreamWriter(Path.Combine(dumpFolderPath, "harmony_evidence.jsonl"), append: false, Encoding.UTF8)) { string value = BuildSummaryJson(dumpId, lastSnapshot); streamWriter.WriteLine(value); foreach (string patchedMethod in lastSnapshot.PatchedMethods) { string value2 = BuildPatchedMethodJson(dumpId, patchedMethod); streamWriter.WriteLine(value2); } foreach (string missingTarget in lastSnapshot.MissingTargets) { string value3 = BuildMissingTargetJson(dumpId, missingTarget); streamWriter.WriteLine(value3); } foreach (string conflict in lastSnapshot.Conflicts) { string value4 = BuildConflictJson(dumpId, conflict); streamWriter.WriteLine(value4); } } ManualLogSource logger4 = _logger; if (logger4 != null) { logger4.LogInfo((object)$"[Eye/HarmonyEvidence] Harmony evidence written for dump {dumpId}."); } } catch (Exception arg) { ManualLogSource logger5 = _logger; if (logger5 != null) { logger5.LogError((object)$"[Eye/HarmonyEvidence] WriteHarmonyEvidence failed for dumpId={dumpId}: {arg}"); } } } private static string BuildSummaryJson(int dumpId, HarmonyIntelligence.HarmonyTelemetry telemetry) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.AppendFormat("\"DumpId\":{0}", dumpId); stringBuilder.Append(",\"Type\":\"Summary\""); stringBuilder.AppendFormat(",\"PatchClassesFound\":{0}", telemetry.PatchClassesFound); stringBuilder.AppendFormat(",\"TargetMethodsMatched\":{0}", telemetry.TargetMethodsMatched); stringBuilder.AppendFormat(",\"PatchesApplied\":{0}", telemetry.PatchesApplied); stringBuilder.Append("}"); return stringBuilder.ToString(); } private static string BuildPatchedMethodJson(int dumpId, string methodSignature) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.AppendFormat("\"DumpId\":{0}", dumpId); stringBuilder.Append(",\"Type\":\"PatchedMethod\""); stringBuilder.AppendFormat(",\"MethodSignature\":\"{0}\"", EscapeJsonString(methodSignature)); stringBuilder.Append("}"); return stringBuilder.ToString(); } private static string BuildMissingTargetJson(int dumpId, string patchClass) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.AppendFormat("\"DumpId\":{0}", dumpId); stringBuilder.Append(",\"Type\":\"MissingTarget\""); stringBuilder.AppendFormat(",\"PatchClass\":\"{0}\"", EscapeJsonString(patchClass)); stringBuilder.Append("}"); return stringBuilder.ToString(); } private static string BuildConflictJson(int dumpId, string conflictDescription) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); stringBuilder.AppendFormat("\"DumpId\":{0}", dumpId); stringBuilder.Append(",\"Type\":\"Conflict\""); stringBuilder.AppendFormat(",\"ConflictDescription\":\"{0}\"", EscapeJsonString(conflictDescription)); stringBuilder.Append("}"); return stringBuilder.ToString(); } private static string EscapeJsonString(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } return value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r", "\\r") .Replace("\n", "\\n") .Replace("\t", "\\t"); } } internal static class HarmonyIntelligence { internal sealed class HarmonyTelemetry { public int PatchClassesFound { get; } public int TargetMethodsMatched { get; } public int PatchesApplied { get; } public IReadOnlyList<string> PatchedMethods { get; } public IReadOnlyList<string> MissingTargets { get; } public IReadOnlyList<string> Conflicts { get; } public HarmonyTelemetry(int patchClassesFound, int targetMethodsMatched, int patchesApplied, IReadOnlyList<string> patchedMethods, IReadOnlyList<string> missingTargets, IReadOnlyList<string> conflicts) { PatchClassesFound = patchClassesFound; TargetMethodsMatched = targetMethodsMatched; PatchesApplied = patchesApplied; PatchedMethods = patchedMethods ?? Array.Empty<string>(); MissingTargets = missingTargets ?? Array.Empty<string>(); Conflicts = conflicts ?? Array.Empty<string>(); } } private sealed class TargetResolutionResult { public List<MethodBase> MatchedMethods { get; } = new List<MethodBase>(); public List<string> MissingTargets { get; } = new List<string>(); } private static readonly string PatchNamespacePrefix = "BlackBox"; private static ManualLogSource _logger; private static Harmony _harmony; private static HarmonyTelemetry _lastSnapshot; public static void Initialize(Harmony harmony, ManualLogSource logger) { _harmony = harmony ?? throw new ArgumentNullException("harmony"); _logger = logger ?? throw new ArgumentNullException("logger"); _logger.LogInfo((object)"[Eye/Harmony] HarmonyIntelligence initialized."); } public static HarmonyTelemetry CaptureSnapshot() { if (_harmony == null) { throw new InvalidOperationException("HarmonyIntelligence.Initialize must be called before CaptureSnapshot."); } try { List<Type> list = FindPatchClasses(); int count = list.Count; TargetResolutionResult targetResolutionResult = ResolveTargets(list); int count2 = targetResolutionResult.MatchedMethods.Count; int count3 = targetResolutionResult.MissingTargets.Count; List<MethodBase> obj = Harmony.GetAllPatchedMethods()?.ToList() ?? new List<MethodBase>(); int count4 = obj.Count; List<string> patchedMethods = (from s in obj.Where((MethodBase m) => m != null).Select(FormatMethodSignature) orderby s select s).ToList(); List<string> source = DetectConflicts(obj); HarmonyTelemetry harmonyTelemetry = (_lastSnapshot = new HarmonyTelemetry(count, count2, count4, patchedMethods, targetResolutionResult.MissingTargets.OrderBy((string s) => s).ToList(), source.OrderBy((string s) => s).ToList())); LogSummary(harmonyTelemetry, count3); return harmonyTelemetry; } catch (Exception arg) { ManualLogSource logger = _logger; if (logger != null) { logger.LogError((object)$"[Eye/Harmony] Failed to capture Harmony snapshot: {arg}"); } return _lastSnapshot = new HarmonyTelemetry(0, 0, 0, Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>()); } } public static HarmonyTelemetry GetLastSnapshot() { return _lastSnapshot; } private static List<Type> FindPatchClasses() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); List<Type> list = new List<Type>(); Type[] array = types; foreach (Type type in array) { if ((string.IsNullOrEmpty(PatchNamespacePrefix) || type.FullName.StartsWith(PatchNamespacePrefix, StringComparison.Ordinal)) && type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Any()) { list.Add(type); } } return list; } private static TargetResolutionResult ResolveTargets(List<Type> patchClasses) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) TargetResolutionResult targetResolutionResult = new TargetResolutionResult(); foreach (Type patchClass in patchClasses) { try { List<MethodInfo> list = new PatchClassProcessor(_harmony, patchClass).Patch(); if (list == null || list.Count == 0) { targetResolutionResult.MissingTargets.Add(patchClass.FullName ?? patchClass.Name); continue; } foreach (MethodInfo item in list) { if (item != null) { targetResolutionResult.MatchedMethods.Add(item); } } } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Harmony] Failed to resolve targets for patch class " + patchClass.FullName + ": " + ex.Message)); } targetResolutionResult.MissingTargets.Add(patchClass.FullName ?? patchClass.Name); } } return targetResolutionResult; } private static List<string> DetectConflicts(List<MethodBase> patchedMethods) { List<string> list = new List<string>(); foreach (MethodBase patchedMethod in patchedMethods) { if (patchedMethod == null) { continue; } try { Patches patchInfo = Harmony.GetPatchInfo(patchedMethod); if (patchInfo != null) { ReadOnlyCollection<string> owners = patchInfo.Owners; if (owners != null && owners.Count > 1) { string text = FormatMethodSignature(patchedMethod); string text2 = string.Join(", ", owners); list.Add(text + " :: Owners=[" + text2 + "]"); } } } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Harmony] Failed to inspect conflict for method " + FormatMethodSignature(patchedMethod) + ": " + ex.Message)); } } } return list; } private static string FormatMethodSignature(MethodBase method) { if (method == null) { return "<null>"; } string text = ((method.DeclaringType != null) ? method.DeclaringType.FullName : "<NoType>"); ParameterInfo[] parameters = method.GetParameters(); string text2 = string.Join(", ", parameters.Select((ParameterInfo p) => p.ParameterType.Name)); return text + "." + method.Name + "(" + text2 + ")"; } private static void LogSummary(HarmonyTelemetry telemetry, int missingTargetsCount) { if (_logger != null) { _logger.LogInfo((object)"[Eye/Harmony] Harmony telemetry captured:"); _logger.LogInfo((object)$"[Eye/Harmony] Patch classes found: {telemetry.PatchClassesFound}"); _logger.LogInfo((object)$"[Eye/Harmony] Target methods matched: {telemetry.TargetMethodsMatched}"); _logger.LogInfo((object)$"[Eye/Harmony] Patches applied: {telemetry.PatchesApplied}"); _logger.LogInfo((object)$"[Eye/Harmony] Missing targets: {missingTargetsCount}"); _logger.LogInfo((object)$"[Eye/Harmony] Conflicts: {telemetry.Conflicts.Count}"); } } } internal static class LedgerRuntime { private static ManualLogSource _logger; internal static readonly string LedgerRootPath = Path.Combine(Paths.ConfigPath, "WubarrksEye", "Ledger"); private static readonly string EvidencePath = Path.Combine(LedgerRootPath, "Evidence"); private static readonly string AggregatesPath = Path.Combine(LedgerRootPath, "Aggregates"); private static readonly string MetaFilePath = Path.Combine(LedgerRootPath, "ledger_meta.txt"); public static void Initialize(ManualLogSource logger) { _logger = logger ?? throw new ArgumentNullException("logger"); EnsureDirectories(); _logger.LogInfo((object)"[Eye/Ledger] LedgerRuntime initialized."); } public static LedgerSnapshot BuildSnapshot() { try { EnsureDirectories(); int currentSizeMB = ComputeDirectorySizeMB(LedgerRootPath); int evidenceCount = CountFilesSafe(EvidencePath); int aggregateCount = CountFilesSafe(AggregatesPath); string lastIngestionTimestamp = ReadMetaTimestampSafe(MetaFilePath); return new LedgerSnapshot(currentSizeMB, evidenceCount, aggregateCount, lastIngestionTimestamp); } catch (Exception arg) { ManualLogSource logger = _logger; if (logger != null) { logger.LogError((object)$"[Eye/Ledger] Failed to build LedgerSnapshot: {arg}"); } return LedgerSnapshot.Empty(); } } public static void UpdateLastIngestionTimestamp(DateTime utcNow) { try { EnsureDirectories(); File.WriteAllText(MetaFilePath, utcNow.ToString("u")); } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Ledger] Failed to write Ledger meta file '" + MetaFilePath + "': " + ex.Message)); } } } private static void EnsureDirectories() { TryCreateDirectory(LedgerRootPath); TryCreateDirectory(EvidencePath); TryCreateDirectory(AggregatesPath); } private static void TryCreateDirectory(string path) { try { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Ledger] Failed to create directory '" + path + "': " + ex.Message)); } } } private static int ComputeDirectorySizeMB(string path) { try { if (!Directory.Exists(path)) { return 0; } long num = 0L; foreach (FileInfo item in new DirectoryInfo(path).EnumerateFiles("*", SearchOption.AllDirectories)) { num += item.Length; } long num2 = 1048576L; long num3 = num / num2; if (num3 > int.MaxValue) { return int.MaxValue; } return (int)num3; } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Ledger] Failed to compute directory size for '" + path + "': " + ex.Message)); } return 0; } } private static int CountFilesSafe(string path) { try { if (!Directory.Exists(path)) { return 0; } return Directory.GetFiles(path, "*", SearchOption.AllDirectories).Length; } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Ledger] Failed to count files in '" + path + "': " + ex.Message)); } return 0; } } private static string ReadMetaTimestampSafe(string metaFile) { try { if (!File.Exists(metaFile)) { return "n/a"; } string text = File.ReadAllText(metaFile).Trim(); if (string.IsNullOrEmpty(text)) { return "n/a"; } return text; } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[Eye/Ledger] Failed to read Ledger meta file '" + metaFile + "': " + ex.Message)); } return "n/a"; } } } internal static class ReflectionUtils { internal static Dictionary<string, string> ExtractFields(object instance) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (instance == null) { return dictionary; } foreach (FieldInfo field in FieldMapCache.GetFields(instance.GetType())) { try { object value = field.GetValue(instance); dictionary[field.Name] = SafeString(value); } catch { dictionary[field.Name] = "[unavailable]"; } } return dictionary; } internal static Dictionary<string, string> ExtractProperties(object instance) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (instance == null) { return dictionary; } foreach (PropertyInfo property in FieldMapCache.GetProperties(instance.GetType())) { try { if (property.GetIndexParameters().Length != 0) { dictionary[property.Name] = "[indexer]"; continue; } object value = property.GetValue(instance, null); dictionary[property.Name] = SafeString(value); } catch { dictionary[property.Name] = "[unavailable]"; } } return dictionary; } internal static List<string> ExtractMethodSignatures(object instance) { List<string> list = new List<string>(); if (instance == null) { return list; } foreach (MethodInfo method in FieldMapCache.GetMethods(instance.GetType())) { try { list.Add(FormatMethodSignature(method)); } catch { list.Add("[unavailable method]"); } } return list; } private static string SafeString(object value) { if (value == null) { return "null"; } try { return value.ToString(); } catch { return "[unstringifiable]"; } } private static string FormatMethodSignature(MethodInfo m) { string text = m.ReturnType?.Name ?? "void"; string name = m.Name; ParameterInfo[] parameters = m.GetParameters(); List<string> list = new List<string>(); ParameterInfo[] array = parameters; foreach (ParameterInfo parameterInfo in array) { try { string text2 = parameterInfo.ParameterType?.Name ?? "unknown"; list.Add(text2 + " " + parameterInfo.Name); } catch { list.Add("unknown_param"); } } return text + " " + name + "(" + string.Join(", ", list) + ")"; } } public sealed class LedgerSnapshot { public int CurrentSizeMB { get; } public int EvidenceCount { get; } public int AggregateCount { get; } public string LastIngestionTimestamp { get; } public LedgerSnapshot(int currentSizeMB, int evidenceCount, int aggregateCount, string lastIngestionTimestamp) { CurrentSizeMB = currentSizeMB; EvidenceCount = evidenceCount; AggregateCount = aggregateCount; LastIngestionTimestamp = lastIngestionTimestamp ?? "n/a"; } public static LedgerSnapshot Empty() { return new LedgerSnapshot(0, 0, 0, "n/a"); } } public sealed class CodexSnapshot { public int CurrentSizeMB { get; } public string LastPromotionTimestamp { get; } public CodexSnapshot(int currentSizeMB, string lastPromotionTimestamp) { CurrentSizeMB = currentSizeMB; LastPromotionTimestamp = lastPromotionTimestamp ?? "n/a"; } public static CodexSnapshot Empty() { return new CodexSnapshot(0, "n/a"); } } public sealed class DumpSnapshot { public string LastDumpTimestamp { get; } public DumpSnapshot(string lastDumpTimestamp) { LastDumpTimestamp = lastDumpTimestamp ?? "n/a"; } public static DumpSnapshot Empty() { return new DumpSnapshot("n/a"); } } internal static class TypeInspector { internal static void DumpTypes(string outputFolder, string fileName, IEnumerable<Type> types, string title) { if (types == null) { return; } Directory.CreateDirectory(outputFolder); string text = Path.Combine(outputFolder, fileName); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# " + title); stringBuilder.AppendLine($"# Generated at {DateTime.Now:O}"); stringBuilder.AppendLine(); int num = 0; int num2 = 0; foreach (Type item in from t in types where t != null orderby t.FullName select t) { if (DumpSingleType(stringBuilder, item)) { num++; } else { num2++; } } if (num2 > 0) { stringBuilder.AppendLine(); stringBuilder.AppendLine($"# Note: Some types could not be fully inspected ({num2} failures)."); stringBuilder.AppendLine("# This does not affect the integrity of the successfully captured data."); } File.WriteAllText(text, stringBuilder.ToString(), n