Decompiled source of The Eye v2.2.0

plugins/WubarrksEye/WubarrksEye.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using WubarrksEye.Core;
using WubarrksEye.Core.Commands;
using WubarrksEye.Core.Dumpers;
using WubarrksEye.Core.Patches;
using WubarrksEye.Core.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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);
		}
	}

	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)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		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 != (Object)null && val == (Object)null) || !_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;
	}

	private static IEnumerable<FieldInfo> SafeFields(Type t)
	{
		FieldInfo[] fields;
		try
		{
			fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
		catch
		{
			yield break;
		}
		FieldInfo[] array = fields;
		FieldInfo[] array2 = array;
		foreach (FieldInfo fieldInfo in array2)
		{
			if (!fieldInfo.IsStatic && !fieldInfo.FieldType.IsPointer && !IsForbidden(fieldInfo.FieldType))
			{
				yield return fieldInfo;
			}
		}
	}
}
namespace WubarrksEye
{
	[BepInPlugin("wubarrk.theeye", "Wubarrk's Eye", "2.2.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "wubarrk.theeye";

		public const string PluginName = "Wubarrk's Eye";

		public const string PluginVersion = "2.2.0";

		private Harmony _harmony;

		private static ManualLogSource _log;

		public static ManualLogSource Log => _log;

		private void Awake()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_009b: Expected O, but got Unknown
			_log = ((BaseUnityPlugin)this).Logger;
			WubarrkLogger.Initialize(((BaseUnityPlugin)this).Logger);
			try
			{
				WubarrkConfig.Bind(((BaseUnityPlugin)this).Config);
				_log.LogInfo((object)"[Eye] WubarrkConfig bound.");
				_harmony = new Harmony("wubarrk.theeye");
				if (WubarrkConfig.ForceGlobalActiveArea.Value)
				{
					ApplyActiveAreaOverride();
				}
				else
				{
					WubarrkLogger.Info("[Eye] ZNetScene active-area override is OFF (config [ZDO] ForceGlobalActiveArea). ZDO dumps read ZDOMan directly.");
				}
				_harmony.PatchAll();
				WubarrkLogger.Info("[Eye] General Harmony patches applied.");
				EyeCommands.Initialize(((BaseUnityPlugin)this).Logger);
				GameObject val = new GameObject("EyeUIManager");
				val.AddComponent<EyeUIManager>();
				val.AddComponent<AutoDumpTrigger>();
				Object.DontDestroyOnLoad((Object)val);
				_log.LogInfo((object)"[Eye] Plugin 2.2.0 initialization complete. Wubarrk's Eye is now watching.");
			}
			catch (Exception arg)
			{
				_log.LogError((object)$"[Eye] Plugin initialization failed: {arg}");
			}
		}

		private void ApplyActiveAreaOverride()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			try
			{
				WubarrkLogger.Info("[Eye] Applying ZNetScene Area Overrides to force global ZDO existence...");
				HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(ZDOExistencePatch), "PrefixOutsideActiveArea", (Type[])null, (Type[])null));
				HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(ZDOExistencePatch), "PrefixInActiveArea1", (Type[])null, (Type[])null));
				HarmonyMethod val3 = new HarmonyMethod(AccessTools.Method(typeof(ZDOExistencePatch), "PrefixInActiveArea2", (Type[])null, (Type[])null));
				HarmonyMethod val4 = new HarmonyMethod(AccessTools.Method(typeof(ZDOExistencePatch), "PrefixInActiveArea3", (Type[])null, (Type[])null));
				MethodInfo methodInfo = AccessTools.Method(typeof(ZNetScene), "OutsideActiveArea", new Type[1] { typeof(Vector3) }, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(ZNetScene), "InActiveArea", new Type[2]
				{
					typeof(Vector2i),
					typeof(Vector3)
				}, (Type[])null);
				MethodInfo methodInfo3 = AccessTools.Method(typeof(ZNetScene), "InActiveArea", new Type[2]
				{
					typeof(Vector2i),
					typeof(Vector2i)
				}, (Type[])null);
				MethodInfo methodInfo4 = AccessTools.Method(typeof(ZNetScene), "InActiveArea", new Type[3]
				{
					typeof(Vector2i),
					typeof(Vector2i),
					typeof(int)
				}, (Type[])null);
				if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || methodInfo4 == null)
				{
					throw new Exception("One or more ZNetScene ActiveArea methods could not be found via reflection.");
				}
				_harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo2, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo3, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo4, val4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WubarrkLogger.Info("[Eye] <color=#00FF00>ZNetScene Area Overrides applied. Every ZDO in the world will be instantiated this session.</color>");
			}
			catch (Exception ex)
			{
				WubarrkLogger.Error("[Eye] FAILED to apply ZNetScene Area Overrides. Exception: " + ex.Message);
				WubarrkLogger.Warn("[Eye] IMPACT: scene/prefab instantiation stays vanilla. ZDO dumps are unaffected. Game will continue to load normally.");
			}
		}

		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}");
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "WubarrksEye";

		public const string PLUGIN_NAME = "WubarrksEye";

		public const string PLUGIN_VERSION = "2.2.0";
	}
}
namespace 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;
				WubarrkLogger.Info("[HarmonyBootstrap] Running PatchAllSafe for attribute-based patches...");
				HarmonyPatcher.PatchAllSafe(harmony, assembly);
				int num = harmony.GetPatchedMethods().Count();
				WubarrkLogger.Info($"[HarmonyBootstrap] Total patched methods after bootstrap: {num}");
			}
			catch (Exception arg)
			{
				WubarrkLogger.Warn($"[HarmonyBootstrap] Fatal error while applying patches: {arg}");
			}
		}
	}
	internal static class HarmonyPatcher
	{
		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 num3 = SafePatchClass(harmony, type, array3);
						num += num3;
					}
					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) != MethodAttributes.PrivateScope)
			{
				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
			{
				WubarrkLogger.Info("[HarmonyPatcher] " + msg);
			}
			catch
			{
			}
		}

		private static void LoggerWarning(string msg)
		{
			try
			{
				WubarrkLogger.Warn("[HarmonyPatcher] " + msg);
			}
			catch
			{
			}
		}

		private static void LoggerDebug(string msg)
		{
			try
			{
				WubarrkLogger.Info("[HarmonyPatcher][Debug] " + msg);
			}
			catch
			{
			}
		}

		private static IEnumerable<MethodInfo> FindSimilarNamedMethods(Type type, string methodName)
		{
			MethodInfo[] methods;
			try
			{
				methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			catch
			{
				yield break;
			}
			string target = methodName.ToLowerInvariant();
			MethodInfo[] array = methods;
			MethodInfo[] array2 = array;
			foreach (MethodInfo methodInfo in array2)
			{
				string text = methodInfo.Name.ToLowerInvariant();
				if (!(text == target) && (text.Contains(target) || target.Contains(text) || LevenshteinDistance(text, target) <= 2))
				{
					yield return methodInfo;
				}
			}
		}

		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 WubarrksEye.Core
{
	internal static class ApiDumpWriter
	{
		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 type3) => type3.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 num = 0; num < names.Length; num++)
				{
					w.WriteLine($"{names[num]} = {(int)values.GetValue(num)}");
				}
			}
			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 methodInfo in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where !methodInfo.IsSpecialName
				orderby methodInfo.Name, methodInfo.GetParameters().Length
				select methodInfo).ToArray();
			if (array3.Length == 0)
			{
				w.WriteLine("<none>");
			}
			else
			{
				MethodInfo[] array4 = array3;
				foreach (MethodInfo m in array4)
				{
					w.WriteLine(FormatFullMethodSignature(m));
				}
			}
			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 ===");
		}

		internal static string GetTypeKind(Type t)
		{
			if (t.IsInterface)
			{
				return "interface";
			}
			if (t.IsEnum)
			{
				return "enum";
			}
			if (t.IsValueType)
			{
				return "struct";
			}
			return "class";
		}

		internal static IEnumerable<Type> GetInheritanceChain(Type t)
		{
			while (t != null)
			{
				yield return t;
				t = t.BaseType;
			}
		}

		internal 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>();
			}
		}

		internal 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);
		}

		internal static string GetPropertyModifiers(PropertyInfo p)
		{
			MethodInfo methodInfo = p.GetGetMethod(nonPublic: true) ?? p.GetSetMethod(nonPublic: true);
			if (!(methodInfo != null))
			{
				return "";
			}
			return GetMethodModifiers(methodInfo);
		}

		internal 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) + "}";
		}

		internal 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";
		}

		internal 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);
		}

		internal 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 num = 0; num < parameters.Length; num++)
			{
				if (num > 0)
				{
					stringBuilder.Append(", ");
				}
				ParameterInfo parameterInfo = parameters[num];
				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 EyeCommands
	{
		private static ManualLogSource _logger;

		public static void Initialize(ManualLogSource logger)
		{
			_logger = logger ?? throw new ArgumentNullException("logger");
			RegisterCommand("dump_eye", "Wubarrk's Eye: full dump. Options: baseline=<dir> (Huginn baseline), nodiff, noml, nozdo, noloc", DumpEye);
			RegisterCommand("eye_status", "Wubarrk's Eye: show dump progress and the last output folder", Status);
			_logger.LogInfo((object)"[Eye/Commands] EyeCommands initialized.");
		}

		private static void RegisterCommand(string name, string description, Action<string[]> handler)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new ConsoleCommand(name, description, (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 Say(string text)
		{
			try
			{
				_logger.LogInfo((object)("[Eye/Commands] " + text));
			}
			catch
			{
			}
			try
			{
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print("[Eye] " + text);
				}
			}
			catch
			{
			}
		}

		private static void DumpEye(string[] args)
		{
			try
			{
				if (DumpManager.IsRunning)
				{
					Say($"A dump is already running ({DumpManager.CurrentPhase}, {DumpManager.OverallProgress:F0}%).");
					return;
				}
				DumpManager.DumpOptions options = DumpManager.DumpOptions.Everything();
				for (int i = 1; i < args.Length; i++)
				{
					string text = args[i];
					if (string.IsNullOrEmpty(text))
					{
						continue;
					}
					string text2 = text.ToLowerInvariant();
					if (text2.StartsWith("baseline="))
					{
						options.BaselineDir = text.Substring("baseline=".Length).Trim(new char[1] { '"' });
						continue;
					}
					switch (text2)
					{
					case "nodiff":
						options.RunHuginnsReport = false;
						break;
					case "noml":
						options.DumpAgentML = false;
						break;
					case "nozdo":
						options.DumpZDOs = false;
						break;
					case "noscene":
						options.DumpScene = false;
						break;
					case "noloc":
						WubarrkConfig.DumpLocalization.Value = false;
						break;
					default:
						Say("Unknown option '" + text + "' ignored. Options: baseline=<dir> nodiff noml nozdo noscene noloc");
						break;
					}
				}
				if (!string.IsNullOrEmpty(options.BaselineDir) && !Directory.Exists(options.BaselineDir))
				{
					Say("Baseline directory not found: " + options.BaselineDir + ". Huginn will fall back to config / most recent dump.");
				}
				string text3 = DumpManager.DefaultDumpRoot();
				Say("Dump started -> " + text3);
				DumpManager.Start(text3, options);
			}
			catch (Exception arg)
			{
				_logger.LogError((object)$"[Eye/Commands] dump_eye failed: {arg}");
			}
		}

		private static void Status(string[] args)
		{
			if (DumpManager.IsRunning)
			{
				Say($"Running: {DumpManager.CurrentPhase} ({DumpManager.ProgressPercentage:F0}%), overall {DumpManager.OverallProgress:F1}%");
			}
			else
			{
				Say((DumpManager.LastDumpRoot != null) ? ("Idle. Last dump: " + DumpManager.LastDumpRoot) : "Idle. No dump this session.");
			}
		}
	}
	internal static class WubarrkConfig
	{
		public enum RamProfile
		{
			Rig_16GB,
			Rig_32GB,
			Rig_64GB_Plus
		}

		public static ConfigEntry<bool> EnableMod;

		public static ConfigEntry<string> PhysicsAuthorityMode;

		public static ConfigEntry<int> DumpMaxFileSizeMB;

		public static ConfigEntry<bool> DeepDiagnostics;

		public static ConfigEntry<int> BurstObjectsPerFrame;

		public static ConfigEntry<RamProfile> SystemMemoryProfile;

		public static ConfigEntry<int> DifferThreadCount;

		public static ConfigEntry<string> ApiAssemblyFilter;

		public static ConfigEntry<bool> ZdoIncludeData;

		public static ConfigEntry<bool> ForceGlobalActiveArea;

		public static ConfigEntry<bool> DumpLocalization;

		public static ConfigEntry<string> HuginnBaselineDir;

		public static ConfigEntry<int> HuginnMaxDeltasPerRecord;

		public static ConfigEntry<bool> AutoDumpOnWorldLoad;

		public static ConfigEntry<float> AutoDumpDelaySeconds;

		public static ConfigEntry<bool> AutoDumpQuit;

		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.");
			DumpMaxFileSizeMB = Config.Bind<int>("Storage", "DumpMaxFileSizeMB", 1024, "Maximum file size for a single JSON dump file in MB before it splits. Default 1024 (1GB).");
			if (DumpMaxFileSizeMB.Value <= 0 || DumpMaxFileSizeMB.Value > 10240)
			{
				DumpMaxFileSizeMB.Value = 1024;
			}
			DeepDiagnostics = Config.Bind<bool>("Diagnostics", "DeepDiagnostics", false, "Extra logging and extra detail. Helps debugging. Slows things down.");
			BurstObjectsPerFrame = Config.Bind<int>("Performance", "BurstObjectsPerFrame", 50, "How many objects the Async Deep Scanner processes per frame. Lower this if the game stutters during a dump.");
			SystemMemoryProfile = Config.Bind<RamProfile>("Hardware", "SystemMemoryProfile", RamProfile.Rig_16GB, "Select your system RAM. Higher profiles drastically speed up processing but will consume more RAM. Default is 16GB (Safe Mode).");
			DifferThreadCount = Config.Bind<int>("Hardware", "DifferThreadCount", 4, "Number of CPU threads Huginn's Report uses for diffing. Clamped between 1 and 16.");
			if (DifferThreadCount.Value < 1)
			{
				DifferThreadCount.Value = 1;
			}
			if (DifferThreadCount.Value > 16)
			{
				DifferThreadCount.Value = 16;
			}
			ApiAssemblyFilter = Config.Bind<string>("API", "ApiAssemblyFilter", "assembly_*,gui_framework,Splatform", "Comma-separated assembly names the API and enum dumps cover. A trailing * is a prefix wildcard. Use * alone to dump every loaded assembly (mscorlib, Unity, BepInEx...), which is 10x the size and mostly noise.");
			ZdoIncludeData = Config.Bind<bool>("ZDO", "ZdoIncludeData", true, "Write every key/value each ZDO carries (health, owner, inventory strings, ...) into ZDO_Dump.json, with keys named via ZDOVars. Off = identity, prefab and position only.");
			ForceGlobalActiveArea = Config.Bind<bool>("ZDO", "ForceGlobalActiveArea", false, "Patch ZNetScene so every ZDO in the world counts as inside the active area for the WHOLE session. The ZDO dump reads ZDOMan directly and does not need this on a host; it makes the game instantiate every object in the world and costs a lot of memory and frame time. Leave off unless you are hunting ghost objects.");
			DumpLocalization = Config.Bind<bool>("Registry", "DumpLocalization", true, "Include the full localization table (every token -> text in the selected language) in Registry_Dump.json. Roughly 10k records.");
			HuginnBaselineDir = Config.Bind<string>("Huginn", "HuginnBaselineDir", "", "Full path of the dump directory Huginn's Report compares against. Empty = the most recent earlier dump under WubarrksEye_Dumps. Override per run with: dump_eye baseline=<dir>");
			HuginnMaxDeltasPerRecord = Config.Bind<int>("Huginn", "HuginnMaxDeltasPerRecord", 200, "Maximum field-level deltas listed for one CHANGED record before the list is truncated.");
			if (HuginnMaxDeltasPerRecord.Value < 1)
			{
				HuginnMaxDeltasPerRecord.Value = 1;
			}
			AutoDumpOnWorldLoad = Config.Bind<bool>("Automation", "AutoDumpOnWorldLoad", false, "Run the full dump automatically once the world is populated. Meant for dedicated servers, which have no console to type dump_eye into. Fires once per process.");
			AutoDumpDelaySeconds = Config.Bind<float>("Automation", "AutoDumpDelaySeconds", 20f, "Seconds to wait after the world is populated before the automatic dump starts, so late mod registrations settle.");
			AutoDumpQuit = Config.Bind<bool>("Automation", "AutoDumpQuit", false, "Quit the application when the automatic dump finishes. Combine with AutoDumpOnWorldLoad for a one-shot headless baseline.");
		}
	}
	internal static class WubarrkLogger
	{
		internal static void Initialize(ManualLogSource log)
		{
		}

		private static string Colorize(string message)
		{
			try
			{
				if (message.Contains("[Eye]"))
				{
					return "<color=#00FFFF>" + message + "</color>";
				}
				if (message.Contains("[Error]"))
				{
					return "<color=#FF0000>" + message + "</color>";
				}
				return message;
			}
			catch
			{
				return message;
			}
		}

		internal static void Info(string message)
		{
			try
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)Colorize("[WubarrksEye] " + message));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"[Eye] Logger Failed: {arg}");
				}
			}
		}

		internal static void Warn(string message)
		{
			try
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)Colorize("[WubarrksEye] " + message));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"[Eye] Logger Failed: {arg}");
				}
			}
		}

		internal static void Error(string message)
		{
			try
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)Colorize("[WubarrksEye] " + message));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"[Eye] Logger Failed: {arg}");
				}
			}
		}

		internal static void MaskedError(string message)
		{
			try
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)Colorize("[WubarrksEye] " + message));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"[Eye] Logger Failed: {arg}");
				}
			}
		}
	}
}
namespace WubarrksEye.Core.UI
{
	public class EyeUIManager : MonoBehaviour
	{
		private bool _showConfigWindow;

		private bool _showHud = true;

		public static bool DumpAgentMLOptions = false;

		public static bool DumpApiOptions = true;

		public static bool DumpPrefabsOptions = true;

		public static bool DumpSceneOptions = true;

		public static bool DumpZDOOptions = true;

		public static bool DumpObjectDBOptions = true;

		public static bool DumpValuesOptions = true;

		public static bool DumpRegistryOptions = true;

		public static bool DumpCallGraphOptions = true;

		public static bool HuginnsReportEnabled = true;

		public static bool HuginnsReportMLFormat = true;

		private Rect _windowRect = new Rect(20f, 20f, 470f, 470f);

		private Rect _hudRect = new Rect(20f, 20f, 320f, 110f);

		private GUIStyle _windowStyle;

		private GUIStyle _labelStyle;

		private GUIStyle _headerStyle;

		private GUIStyle _buttonStyle;

		private bool _stylesInitialized;

		public static EyeUIManager Instance { get; private set; }

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				WubarrkLogger.Info("[Eye.UI] Headless (no graphics device): HUD and F8 window disabled. Use dump_eye or [Automation] AutoDumpOnWorldLoad.");
				((Behaviour)this).enabled = false;
			}
			else
			{
				WubarrkLogger.Info("[Eye.UI] UIManager initialized. Press F8 to toggle Config window, F9 to toggle HUD.");
			}
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)289))
			{
				_showConfigWindow = !_showConfigWindow;
			}
			if (Input.GetKeyDown((KeyCode)290))
			{
				_showHud = !_showHud;
			}
		}

		private void InitializeStyles()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			if (!_stylesInitialized)
			{
				Texture2D val = new Texture2D(1, 1);
				val.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.85f));
				val.Apply();
				Texture2D val2 = new Texture2D(1, 1);
				val2.SetPixel(0, 0, new Color(0.2f, 0.2f, 0.2f, 0.9f));
				val2.Apply();
				_windowStyle = new GUIStyle(GUI.skin.window);
				_windowStyle.normal.background = val;
				_windowStyle.normal.textColor = new Color(1f, 0.84f, 0f);
				_windowStyle.focused.textColor = new Color(1f, 0.84f, 0f);
				_windowStyle.onNormal.textColor = new Color(1f, 0.84f, 0f);
				_labelStyle = new GUIStyle(GUI.skin.label);
				_labelStyle.normal.textColor = new Color(1f, 0.84f, 0f);
				_headerStyle = new GUIStyle(GUI.skin.label);
				_headerStyle.normal.textColor = new Color(1f, 0.84f, 0f);
				_headerStyle.fontStyle = (FontStyle)1;
				_headerStyle.fontSize = 14;
				_buttonStyle = new GUIStyle(GUI.skin.button);
				_buttonStyle.normal.background = val2;
				_buttonStyle.normal.textColor = new Color(1f, 0.84f, 0f);
				_stylesInitialized = true;
			}
		}

		private void OnGUI()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			InitializeStyles();
			if (_showHud && !_showConfigWindow)
			{
				DrawHUD();
			}
			if (_showConfigWindow)
			{
				_windowRect = GUI.Window(9999, _windowRect, new WindowFunction(DrawConfigWindow), "TheEye 2.2.0 - Developer Console", _windowStyle);
			}
		}

		private void DrawHUD()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			GUI.Box(_hudRect, "", _windowStyle);
			GUILayout.BeginArea(_hudRect);
			GUILayout.Label("TheEye HUD 2.2.0", _headerStyle, Array.Empty<GUILayoutOption>());
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				int num = ((ZDOMan.instance != null) ? ZDOMan.instance.m_objectsByID.Count : 0);
				GUILayout.Label($"Active ZDOs: {num}", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Waiting for game...", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			if (DumpManager.IsRunning)
			{
				GUILayout.Label($"Total Progress: {DumpManager.OverallProgress:F1}%", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Phase: {DumpManager.CurrentPhase} ({DumpManager.ProgressPercentage:F0}%)", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Status: Idle", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndArea();
		}

		private void DrawConfigWindow(int windowID)
		{
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("Deep Dump Controls", _headerStyle, Array.Empty<GUILayoutOption>());
			if (DumpManager.IsRunning)
			{
				GUILayout.Label($"Total Progress: {DumpManager.OverallProgress:F1}%", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Phase: {DumpManager.CurrentPhase} ({DumpManager.ProgressPercentage:F0}%)", _labelStyle, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Cancel Dump", _buttonStyle, Array.Empty<GUILayoutOption>()))
				{
					DumpManager.Cancel();
				}
			}
			else
			{
				DumpAgentMLOptions = GUILayout.Toggle(DumpAgentMLOptions, "Also build the AI Agent ML bundle (.zip of .jsonl)", Array.Empty<GUILayoutOption>());
				DumpApiOptions = GUILayout.Toggle(DumpApiOptions, "Dump API / Types (game assemblies, full member surface)", Array.Empty<GUILayoutOption>());
				DumpPrefabsOptions = GUILayout.Toggle(DumpPrefabsOptions, "Dump Prefabs (component lists)", Array.Empty<GUILayoutOption>());
				DumpSceneOptions = GUILayout.Toggle(DumpSceneOptions, "Dump Active Scene Objects", Array.Empty<GUILayoutOption>());
				DumpZDOOptions = GUILayout.Toggle(DumpZDOOptions, "Dump ZDO State (with key/values)", Array.Empty<GUILayoutOption>());
				DumpObjectDBOptions = GUILayout.Toggle(DumpObjectDBOptions, "Dump ObjectDB (Items & Recipes)", Array.Empty<GUILayoutOption>());
				DumpValuesOptions = GUILayout.Toggle(DumpValuesOptions, "Dump Values (field contents)", Array.Empty<GUILayoutOption>());
				DumpRegistryOptions = GUILayout.Toggle(DumpRegistryOptions, "Dump Registries (enums, spawns, env, events, pieces, commands, localization)", Array.Empty<GUILayoutOption>());
				DumpCallGraphOptions = GUILayout.Toggle(DumpCallGraphOptions, "Dump Call Graph (IL call / field edges / RPC names)", Array.Empty<GUILayoutOption>());
				GUILayout.Space(10f);
				GUILayout.Label("Huginn's Report (structural diff against a baseline)", _headerStyle, Array.Empty<GUILayoutOption>());
				HuginnsReportEnabled = GUILayout.Toggle(HuginnsReportEnabled, "Run Huginn's Report after the dump", Array.Empty<GUILayoutOption>());
				if (HuginnsReportEnabled)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					if (GUILayout.Toggle(!HuginnsReportMLFormat, "Human Readable (.json)", Array.Empty<GUILayoutOption>()))
					{
						HuginnsReportMLFormat = false;
					}
					if (GUILayout.Toggle(HuginnsReportMLFormat, "AI Agent Format (.jsonl)", Array.Empty<GUILayoutOption>()))
					{
						HuginnsReportMLFormat = true;
					}
					GUILayout.EndHorizontal();
					string text = ((WubarrkConfig.HuginnBaselineDir != null) ? WubarrkConfig.HuginnBaselineDir.Value : "");
					GUILayout.Label(string.IsNullOrEmpty(text) ? "<color=#888888>Baseline: most recent earlier dump (set [Huginn] HuginnBaselineDir or use dump_eye baseline=<dir>)</color>" : ("<color=#888888>Baseline: " + text + "</color>"), _labelStyle, Array.Empty<GUILayoutOption>());
				}
				GUILayout.Space(10f);
				if (GUILayout.Button("Start Dump", _buttonStyle, Array.Empty<GUILayoutOption>()))
				{
					DumpManager.DumpOptions options = new DumpManager.DumpOptions
					{
						DumpAgentML = DumpAgentMLOptions,
						DumpAPI = DumpApiOptions,
						DumpPrefabs = DumpPrefabsOptions,
						DumpScene = DumpSceneOptions,
						DumpZDOs = DumpZDOOptions,
						DumpObjectDB = DumpObjectDBOptions,
						DumpValues = DumpValuesOptions,
						DumpRegistry = DumpRegistryOptions,
						DumpCallGraph = DumpCallGraphOptions,
						RunHuginnsReport = HuginnsReportEnabled,
						HuginnsReportMLFormat = HuginnsReportMLFormat,
						BaselineDir = null
					};
					DumpManager.Start(DumpManager.DefaultDumpRoot(), options);
				}
				if (DumpManager.LastDumpRoot != null)
				{
					GUILayout.Label("<color=#888888>Last: " + DumpManager.LastDumpRoot + "</color>", _labelStyle, Array.Empty<GUILayoutOption>());
				}
			}
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
		}
	}
}
namespace WubarrksEye.Core.Patches
{
	public static class ZDOExistencePatch
	{
		public static bool PrefixOutsideActiveArea(ref bool __result)
		{
			__result = false;
			return false;
		}

		public static bool PrefixInActiveArea1(ref bool __result)
		{
			__result = true;
			return false;
		}

		public static bool PrefixInActiveArea2(ref bool __result)
		{
			__result = true;
			return false;
		}

		public static bool PrefixInActiveArea3(ref bool __result)
		{
			__result = true;
			return false;
		}
	}
}
namespace WubarrksEye.Core.Dumpers
{
	public class ApiExtractor : IDataExtractor
	{
		private const BindingFlags Declared = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public string ExtractorName => "API Reflection";

		public string OutputFileName => "API_Dump.json";

		public IEnumerator ExtractData(StreamWriter writer, int maxBytes)
		{
			return Extract(writer, minifiedJsonl: false);
		}

		public IEnumerator ExtractDataToZip(StreamWriter writer)
		{
			return Extract(writer, minifiedJsonl: true);
		}

		internal static bool IsGameAssembly(Assembly asm)
		{
			string name;
			try
			{
				name = asm.GetName().Name;
			}
			catch
			{
				return false;
			}
			string text = ((WubarrkConfig.ApiAssemblyFilter != null) ? WubarrkConfig.ApiAssemblyFilter.Value : "");
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "assembly_*,gui_framework,Splatform";
			}
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0)
				{
					continue;
				}
				if (text2 == "*")
				{
					return true;
				}
				if (text2.EndsWith("*"))
				{
					if (name.StartsWith(text2.Substring(0, text2.Length - 1), StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
				else if (string.Equals(name, text2, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool IsCompilerGenerated(Type t)
		{
			string text = t.FullName ?? t.Name;
			if (text.IndexOf('<') < 0 && text.IndexOf("c__DisplayClass", StringComparison.Ordinal) < 0 && text.IndexOf("d__", StringComparison.Ordinal) < 0)
			{
				return text.IndexOf("PrivateImplementationDetails", StringComparison.Ordinal) >= 0;
			}
			return true;
		}

		internal static List<Type> GameTypes()
		{
			List<Type> list = new List<Type>();
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (!IsGameAssembly(assembly))
				{
					continue;
				}
				Type[] array;
				try
				{
					array = assembly.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					array = ex.Types.Where((Type t) => t != null).ToArray();
				}
				catch
				{
					continue;
				}
				Type[] array2 = array;
				foreach (Type type in array2)
				{
					if (!(type == null) && !IsCompilerGenerated(type))
					{
						list.Add(type);
					}
				}
			}
			list.Sort((Type a, Type b) => string.CompareOrdinal(a.FullName, b.FullName));
			return list;
		}

		private IEnumerator Extract(StreamWriter writer, bool minifiedJsonl)
		{
			List<Type> types = GameTypes();
			int total = types.Count;
			int batchSize = 50;
			if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_32GB)
			{
				batchSize = 200;
			}
			if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_64GB_Plus)
			{
				batchSize = 1000;
			}
			bool isFirst = true;
			for (int i = 0; i < total; i++)
			{
				if (DumpManager._cancelRequested)
				{
					break;
				}
				Type type = types[i];
				JObject val;
				try
				{
					val = DumpType(type);
				}
				catch (Exception ex)
				{
					val = new JObject();
					val["Type"] = JToken.op_Implicit("API_Type");
					val["FullName"] = JToken.op_Implicit(type.FullName);
					val["<error>"] = JToken.op_Implicit(ex.GetType().Name);
				}
				if (minifiedJsonl)
				{
					writer.WriteLine(((JToken)val).ToString((Formatting)0, Array.Empty<JsonConverter>()));
				}
				else
				{
					if (!isFirst)
					{
						writer.Write(",\n");
					}
					writer.Write(((JToken)val).ToString((Formatting)1, Array.Empty<JsonConverter>()));
					isFirst = false;
				}
				if (i % batchSize == 0)
				{
					writer.Flush();
					DumpManager._progress = (float)i / (float)Math.Max(1, total) * 100f;
					yield return null;
				}
			}
			writer.Flush();
			DumpManager._progress = 100f;
			WubarrkLogger.Info($"[Eye.API] {total} types written.");
		}

		internal static string TypeName(Type t)
		{
			if (t == null)
			{
				return null;
			}
			if (t.IsByRef)
			{
				return TypeName(t.GetElementType()) + "&";
			}
			if (t.IsPointer)
			{
				return TypeName(t.GetElementType()) + "*";
			}
			if (t.IsArray)
			{
				return TypeName(t.GetElementType()) + "[" + new string(',', t.GetArrayRank() - 1) + "]";
			}
			if (t.IsGenericParameter)
			{
				return t.Name;
			}
			if (t.IsGenericType)
			{
				Type genericTypeDefinition = t.GetGenericTypeDefinition();
				string text = genericTypeDefinition.FullName ?? genericTypeDefinition.Name;
				int num = text.IndexOf('`');
				if (num >= 0)
				{
					text = text.Substring(0, num);
				}
				return text + "<" + string.Join(",", t.GetGenericArguments().Select(TypeName)) + ">";
			}
			return t.FullName ?? t.Name;
		}

		private static string Visibility(MethodBase m)
		{
			return ApiDumpWriter.GetVisibility(m);
		}

		private static string FormatSignature(MethodInfo m)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(ApiDumpWriter.GetMethodModifiers(m)).Append(' ');
			stringBuilder.Append(TypeName(m.ReturnType)).Append(' ').Append(m.Name);
			if (m.IsGenericMethod)
			{
				stringBuilder.Append('<').Append(string.Join(", ", from x in m.GetGenericArguments()
					select x.Name)).Append('>');
			}
			stringBuilder.Append('(');
			ParameterInfo[] parameters = m.GetParameters();
			for (int num = 0; num < parameters.Length; num++)
			{
				if (num > 0)
				{
					stringBuilder.Append(", ");
				}
				if (parameters[num].IsOut)
				{
					stringBuilder.Append("out ");
				}
				else if (parameters[num].ParameterType.IsByRef)
				{
					stringBuilder.Append("ref ");
				}
				stringBuilder.Append(TypeName(parameters[num].ParameterType.IsByRef ? parameters[num].ParameterType.GetElementType() : parameters[num].ParameterType));
				stringBuilder.Append(' ').Append(parameters[num].Name);
			}
			stringBuilder.Append(')');
			return stringBuilder.ToString();
		}

		private static string MethodKey(MethodBase m)
		{
			string text = m.Name;
			if (m.IsGenericMethod)
			{
				text = text + "<" + string.Join(",", from a in m.GetGenericArguments()
					select a.Name) + ">";
			}
			return text + "(" + string.Join(",", from p in m.GetParameters()
				select TypeName(p.ParameterType)) + ")";
		}

		private static JObject DumpType(Type t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Expected O, but got Unknown
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_0550: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Expected O, but got Unknown
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0612: Expected O, but got Unknown
			//IL_068f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Expected O, but got Unknown
			//IL_07e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ed: Expected O, but got Unknown
			//IL_07ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f4: Expected O, but got Unknown
			//IL_0836: Unknown result type (might be due to invalid IL or missing references)
			//IL_083d: Expected O, but got Unknown
			JObject val = new JObject();
			val["Type"] = JToken.op_Implicit("API_Type");
			val["FullName"] = JToken.op_Implicit(t.FullName);
			val["Namespace"] = JToken.op_Implicit(t.Namespace);
			val["Assembly"] = JToken.op_Implicit(t.Assembly.GetName().Name);
			val["Kind"] = JToken.op_Implicit(ApiDumpWriter.GetTypeKind(t));
			val["IsAbstract"] = JToken.op_Implicit(t.IsAbstract);
			val["IsSealed"] = JToken.op_Implicit(t.IsSealed);
			val["IsNested"] = JToken.op_Implicit(t.IsNested);
			val["Visibility"] = JToken.op_Implicit((!t.IsNested) ? (t.IsPublic ? "public" : "internal") : (t.IsNestedPublic ? "public" : (t.IsNestedFamily ? "protected" : (t.IsNestedAssembly ? "internal" : "private"))));
			val["IsGenericType"] = JToken.op_Implicit(t.IsGenericType);
			if (t.IsGenericType)
			{
				val["GenericArguments"] = (JToken)new JArray((object)(from a in t.GetGenericArguments()
					select a.Name));
			}
			val["BaseType"] = JToken.op_Implicit(TypeName(t.BaseType));
			val["InheritanceChain"] = (JToken)new JArray((object)ApiDumpWriter.GetInheritanceChain(t).Skip(1).Select(TypeName));
			val["Implements"] = (JToken)new JArray((object)t.GetInterfaces().Select(TypeName).OrderBy<string, string>((string s) => s, StringComparer.Ordinal));
			val["Attributes"] = (JToken)new JArray((object)ApiDumpWriter.SafeGetCustomAttributes(t).OrderBy<string, string>((string s) => s, StringComparer.Ordinal));
			if (t.IsEnum)
			{
				JObject val2 = new JObject();
				val["EnumUnderlying"] = JToken.op_Implicit(TypeName(Enum.GetUnderlyingType(t)));
				val["IsFlags"] = JToken.op_Implicit(t.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Length != 0);
				try
				{
					Type underlyingType = Enum.GetUnderlyingType(t);
					string[] names = Enum.GetNames(t);
					Array values = Enum.GetValues(t);
					for (int num = 0; num < names.Length; num++)
					{
						object obj = Convert.ChangeType(values.GetValue(num), underlyingType, CultureInfo.InvariantCulture);
						val2[names[num]] = JToken.op_Implicit(Convert.ToString(obj, CultureInfo.InvariantCulture));
					}
				}
				catch (Exception ex)
				{
					val2["<error>"] = JToken.op_Implicit(ex.GetType().Name);
				}
				val["EnumValues"] = (JToken)(object)val2;
			}
			JObject val3 = new JObject();
			foreach (FieldInfo item in t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).OrderBy<FieldInfo, string>((FieldInfo f) => f.Name, StringComparer.Ordinal))
			{
				if (item.Name.IndexOf('<') >= 0)
				{
					continue;
				}
				string text = TypeName(item.FieldType) + " " + ApiDumpWriter.GetFieldModifiers(item);
				if (item.IsLiteral && !item.IsInitOnly)
				{
					try
					{
						text = text + " = " + Convert.ToString(item.GetRawConstantValue(), CultureInfo.InvariantCulture);
					}
					catch
					{
					}
				}
				val3[item.Name] = JToken.op_Implicit(text);
			}
			val["Fields"] = (JToken)(object)val3;
			JObject val4 = new JObject();
			foreach (PropertyInfo item2 in t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).OrderBy<PropertyInfo, string>((PropertyInfo p) => p.Name, StringComparer.Ordinal))
			{
				string text2 = item2.Name;
				ParameterInfo[] indexParameters = item2.GetIndexParameters();
				if (indexParameters.Length != 0)
				{
					text2 = text2 + "[" + string.Join(",", indexParameters.Select((ParameterInfo x) => TypeName(x.ParameterType))) + "]";
				}
				val4[text2] = JToken.op_Implicit(TypeName(item2.PropertyType) + " " + ApiDumpWriter.GetPropertyModifiers(item2) + " " + ApiDumpWriter.GetPropertyAccessorFlags(item2));
			}
			val["Properties"] = (JToken)(object)val4;
			JObject val5 = new JObject();
			foreach (EventInfo item3 in t.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).OrderBy<EventInfo, string>((EventInfo e) => e.Name, StringComparer.Ordinal))
			{
				MethodInfo addMethod = item3.GetAddMethod(nonPublic: true);
				val5[item3.Name] = JToken.op_Implicit(TypeName(item3.EventHandlerType) + ((addMethod != null) ? (" " + ApiDumpWriter.GetMethodModifiers(addMethod)) : ""));
			}
			val["Events"] = (JToken)(object)val5;
			JObject val6 = new JObject();
			foreach (ConstructorInfo item4 in t.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).OrderBy<ConstructorInfo, string>(MethodKey, StringComparer.Ordinal))
			{
				val6[MethodKey(item4)] = JToken.op_Implicit(ApiDumpWriter.GetMethodModifiers(item4));
			}
			val["Constructors"] = (JToken)(object)val6;
			JObject val7 = new JObject();
			foreach (MethodInfo item5 in (from m in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where !m.IsSpecialName
				select m).OrderBy<MethodInfo, string>(MethodKey, StringComparer.Ordinal))
			{
				string text3 = MethodKey(item5);
				if (val7[text3] != null)
				{
					text3 = text3 + "#" + item5.MetadataToken;
				}
				val7[text3] = JToken.op_Implicit(FormatSignature(item5));
			}
			val["Methods"] = (JToken)(object)val7;
			val["NestedTypes"] = (JToken)new JArray((object)(from n in t.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic)
				where !IsCompilerGenerated(n)
				select n.Name).OrderBy<string, string>((string s) => s, StringComparer.Ordinal));
			JObject val8 = new JObject();
			val8["IsMonoBehaviour"] = JToken.op_Implicit(typeof(MonoBehaviour).IsAssignableFrom(t));
			val8["IsScriptableObject"] = JToken.op_Implicit(typeof(ScriptableObject).IsAssignableFrom(t));
			JArray val9 = new JArray();
			try
			{
				foreach (RequireComponent item6 in t.GetCustomAttributes(inherit: true).OfType<RequireComponent>())
				{
					if (item6.m_Type0 != null)
					{
						val9.Add(JToken.op_Implicit(TypeName(item6.m_Type0)));
					}
					if (item6.m_Type1 != null)
					{
						val9.Add(JToken.op_Implicit(TypeName(item6.m_Type1)));
					}
					if (item6.m_Type2 != null)
					{
						val9.Add(JToken.op_Implicit(TypeName(item6.m_Type2)));
					}
				}
			}
			catch
			{
			}
			val8["RequiredComponents"] = (JToken)(object)val9;
			val["Unity"] = (JToken)(object)val8;
			return val;
		}
	}
	public class CallGraphExtractor : IDataExtractor
	{
		private static OpCode[] _singleByteOpCodes;

		private static OpCode[] _twoByteOpCodes;

		public string ExtractorName => "Call Graph";

		public string OutputFileName => "CallGraph_Dump.json";

		public IEnumerator ExtractData(StreamWriter writer, int maxBytes)
		{
			return Extract(writer, minifiedJsonl: false, maxBytes);
		}

		public IEnumerator ExtractDataToZip(StreamWriter writer)
		{
			return Extract(writer, minifiedJsonl: true, int.MaxValue);
		}

		private IEnumerator Extract(StreamWriter writer, bool minifiedJsonl, int maxBytes)
		{
			Assembly assembly = typeof(ZNetScene).Assembly;
			Type[] types;
			try
			{
				types = assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				types = ex.Types.Where((Type t) => t != null).ToArray();
			}
			catch (Exception ex2)
			{
				WubarrkLogger.Error("[Eye.CallGraph] Could not enumerate types in " + assembly.GetName().Name + ": " + ex2.Message);
				yield break;
			}
			Array.Sort(types, (Type a, Type b) => string.CompareOrdinal(a.FullName, b.FullName));
			Dictionary<string, List<string>> calledByMap = new Dictionary<string, List<string>>();
			List<JObject> rpcRegistrations = new List<JObject>();
			int methodCount = 0;
			int typeIndex = 0;
			int batchSize = ((WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_32GB) ? 200 : ((WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_64GB_Plus) ? 1000 : 50));
			bool isFirst = true;
			long written = 0L;
			bool truncated = false;
			Type[] array = types;
			foreach (Type type in array)
			{
				if (DumpManager._cancelRequested || truncated)
				{
					break;
				}
				List<MethodBase> list;
				try
				{
					list = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Cast<MethodBase>().Concat(type.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
						.ToList();
				}
				catch
				{
					typeIndex++;
					continue;
				}
				foreach (MethodBase item in list)
				{
					if (DumpManager._cancelRequested)
					{
						break;
					}
					if (written >= maxBytes)
					{
						truncated = true;
						break;
					}
					JObject val = null;
					try
					{
						val = WalkMethod(item, calledByMap, rpcRegistrations);
					}
					catch (Exception ex3)
					{
						WubarrkLogger.Warn("[Eye.CallGraph] Skipped " + type.Name + "." + item.Name + ": " + ex3.GetType().Name);
					}
					if (val != null)
					{
						writeObj(val);
						methodCount++;
						if (methodCount % batchSize == 0)
						{
							writer.Flush();
							DumpManager._progress = (float)typeIndex / (float)Math.Max(1, types.Length) * 100f;
							yield return null;
						}
					}
				}
				typeIndex++;
			}
			if (truncated)
			{
				WubarrkLogger.Warn($"[Eye.CallGraph] Hit the {maxBytes / 1048576} MB cap after {methodCount} methods; forward edges truncated.");
			}
			foreach (KeyValuePair<string, List<string>> item2 in calledByMap.OrderBy<KeyValuePair<string, List<string>>, string>((KeyValuePair<string, List<string>> k) => k.Key, StringComparer.Ordinal))
			{
				if (DumpManager._cancelRequested)
				{
					break;
				}
				JObject val2 = new JObject
				{
					["Type"] = JToken.op_Implicit("Index"),
					["Kind"] = JToken.op_Implicit("CalledBy"),
					["Method"] = JToken.op_Implicit(item2.Key)
				};
				object[] array2 = item2.Value.Distinct().OrderBy<string, string>((string c) => c, StringComparer.Ordinal).ToArray();
				val2["Callers"] = (JToken)new JArray(array2);
				writeObj(val2);
				methodCount++;
				if (methodCount % batchSize == 0)
				{
					writer.Flush();
					yield return null;
				}
			}
			foreach (JObject item3 in rpcRegistrations.OrderBy<JObject, string>((JObject r) => (string)r["RpcName"], StringComparer.Ordinal).ThenBy<JObject, string>((JObject r) => (string)r["Registrar"], StringComparer.Ordinal))
			{
				if (!DumpManager._cancelRequested)
				{
					writeObj(item3);
					methodCount++;
					continue;
				}
				break;
			}
			writer.Flush();
			DumpManager._progress = 100f;
			WubarrkLogger.Info($"[Eye.CallGraph] {methodCount} records written across {types.Length} types, {rpcRegistrations.Count} RPC registrations.");
			void writeObj(JObject val3)
			{
				string text = ((JToken)val3).ToString((Formatting)(!minifiedJsonl), Array.Empty<JsonConverter>());
				if (minifiedJsonl)
				{
					writer.WriteLine(text);
				}
				else
				{
					if (!isFirst)
					{
						writer.Write(",\n");
					}
					writer.Write(text);
					isFirst = false;
				}
				written += text.Length + 2;
			}
		}

		private JObject WalkMethod(MethodBase method, Dictionary<string, List<string>> calledByMap, List<JObject> rpcRegistrations)
		{
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Expected O, but got Unknown
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Expected O, but got Unknown
			MethodBody methodBody = null;
			try
			{
				methodBody = method.GetMethodBody();
			}
			catch
			{
			}
			if (methodBody == null)
			{
				return null;
			}
			byte[] iLAsByteArray = methodBody.GetILAsByteArray();
			if (iLAsByteArray == null || iLAsByteArray.Length == 0)
			{
				return null;
			}
			Module module = method.Module;
			Type[] genericTypeArguments = ((method.DeclaringType != null && method.DeclaringType.IsGenericType) ? method.DeclaringType.GetGenericArguments() : null);
			Type[] genericMethodArguments = (method.IsGenericMethod ? method.GetGenericArguments() : null);
			string text = FormatSignature(method);
			string text2 = method.DeclaringType?.Name + "." + method.Name + "(" + string.Join(",", from p in method.GetParameters()
				select p.ParameterType.FullName ?? p.ParameterType.Name) + ")";
			JObject val = new JObject();
			val["Type"] = JToken.op_Implicit(method.DeclaringType?.Name ?? "Unknown");
			val["Method"] = JToken.op_Implicit(method.Name);
			val["Signature"] = JToken.op_Implicit(text);
			try
			{
				val["Token"] = JToken.op_Implicit(method.MetadataToken);
			}
			catch
			{
				val["Token"] = JToken.op_Implicit(0);
			}
			MethodInfo methodInfo = method as MethodInfo;
			bool flag = methodInfo != null && methodInfo.IsVirtual && methodInfo.GetBaseDefinition() != methodInfo;
			val["ChainsToBase"] = (JToken)(flag ? ((object)JToken.op_Implicit(false)) : ((object)JValue.CreateNull()));
			JArray val2 = new JArray();
			JArray val3 = new JArray();
			JArray val4 = new JArray();
			int num = 0;
			string text3 = null;
			int num2 = 0;
			while (num2 < iLAsByteArray.Length)
			{
				OpCode opCode;
				if (iLAsByteArray[num2] == 254)
				{
					if (num2 + 1 >= iLAsByteArray.Length)
					{
						break;
					}
					opCode = _twoByteOpCodes[iLAsByteArray[num2 + 1]];
					num2 += 2;
				}
				else
				{
					opCode = _singleByteOpCodes[iLAsByteArray[num2]];
					num2++;
				}
				if (opCode.OperandType == OperandType.InlineMethod)
				{
					if (num2 + 4 > iLAsByteArray.Length)
					{
						break;
					}
					int metadataToken = BitConverter.ToInt32(iLAsByteArray, num2);
					num2 += 4;
					try
					{
						MethodBase methodBase = module.ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
						if (methodBase != null)
						{
							string text4 = methodBase.DeclaringType?.Name + "." + methodBase.Name + "(" + string.Join(",", from p in methodBase.GetParameters()
								select p.ParameterType.FullName ?? p.ParameterType.Name) + ")";
							JObject val5 = new JObject();
							val5["Target"] = JToken.op_Implicit(text4);
							val5["Op"] = JToken.op_Implicit(opCode.Name);
							val2.Add((JToken)(object)val5);
							if (text3 != null && methodBase.Name == "Register" && methodBase.DeclaringType != null && (methodBase.DeclaringType == typeof(ZNetView) || methodBase.DeclaringType == typeof(ZRoutedRpc) || methodBase.DeclaringType == typeof(ZRpc)))
							{
								JObject val6 = new JObject();
								val6["Type"] = JToken.op_Implicit("Index");
								val6["Kind"] = JToken.op_Implicit("RpcRegistration");
								val6["RpcName"] = JToken.op_Implicit(text3);
								val6["Via"] = JToken.op_Implicit(methodBase.DeclaringType.Name);
								val6["Registrar"] = JToken.op_Implicit(text2);
								rpcRegistrations.Add(val6);
								text3 = null;
							}
							if (!calledByMap.TryGetValue(text4, out var value))
							{
								value = (calledByMap[text4] = new List<string>());
							}
							value.Add(text2);
							if (flag && opCode == OpCodes.Call && methodBase is MethodInfo methodInfo2 && methodInfo2.Name == methodInfo.Name && methodInfo2.DeclaringType != null && methodInfo.DeclaringType != null && methodInfo2.DeclaringType != methodInfo.DeclaringType && methodInfo2.DeclaringType.IsAssignableFrom(methodInfo.DeclaringType))
							{
								val["ChainsToBase"] = JToken.op_Implicit(true);
							}
						}
					}
					catch
					{
						num++;
					}
					continue;
				}
				if (opCode.OperandType == OperandType.InlineField)
				{
					if (num2 + 4 > iLAsByteArray.Length)
					{
						break;
					}
					int metadataToken2 = BitConverter.ToInt32(iLAsByteArray, num2);
					num2 += 4;
					try
					{
						FieldInfo fieldInfo = module.ResolveField(metadataToken2, genericTypeArguments, genericMethodArguments);
						if (fieldInfo != null)
						{
							string text5 = fieldInfo.DeclaringType?.Name + "." + fieldInfo.Name;
							if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldsfld || opCode == OpCodes.Ldflda || opCode == OpCodes.Ldsflda)
							{
								val3.Add(JToken.op_Implicit(text5));
							}
							else if (opCode == OpCodes.Stfld || opCode == OpCodes.Stsfld)
							{
								val4.Add(JToken.op_Implicit(text5));
							}
						}
					}
					catch
					{
						num++;
					}
					continue;
				}
				if (opCode.OperandType == OperandType.InlineSwitch)
				{
					if (num2 + 4 > iLAsByteArray.Length)
					{
						break;
					}
					int num3 = BitConverter.ToInt32(iLAsByteArray, num2);
					num2 += 4;
					num2 += num3 * 4;
					continue;
				}
				switch (opCode.OperandType)
				{
				case OperandType.InlineString:
					if (num2 + 4 > iLAsByteArray.Length)
					{
						num2 = iLAsByteArray.Length;
						break;
					}
					try
					{
						text3 = module.ResolveString(BitConverter.ToInt32(iLAsByteArray, num2));
					}
					catch
					{
					}
					num2 += 4;
					break;
				case OperandType.InlineBrTarget:
				case OperandType.InlineI:
				case OperandType.InlineSig:
				case OperandType.InlineTok:
				case OperandType.InlineType:
				case OperandType.ShortInlineR:
					num2 += 4;
					break;
				case OperandType.InlineI8:
				case OperandType.InlineR:
					num2 += 8;
					break;
				case OperandType.InlineVar:
					num2 += 2;
					break;
				case OperandType.ShortInlineBrTarget:
				case OperandType.ShortInlineI:
				case OperandType.ShortInlineVar:
					num2++;
					break;
				}
			}
			val["Calls"] = (JToken)(object)val2;
			val["Reads"] = (JToken)(object)val3;
			val["Writes"] = (JToken)(object)val4;
			val["Unresolved"] = JToken.op_Implicit(num);
			return val;
		}

		static CallGraphExtractor()
		{
			_singleByteOpCodes = new OpCode[256];
			_twoByteOpCodes = new OpCode[256];
			FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!(fieldInfo.FieldType != typeof(OpCode)))
				{
					OpCode opCode = (OpCode)fieldInfo.GetValue(null);
					ushort num = (ushort)opCode.Value;
					if (num < 256)
					{
						_singleByteOpCodes[num] = opCode;
					}
					else if ((num & 0xFF00) == 65024)
					{
						_twoByteOpCodes[num & 0xFF] = opCode;
					}
				}
			}
		}

		private string FormatSignature(MethodBase m)
		{
			string text = "";
			if (m.IsPublic)
			{
				text += "public ";
			}
			else if (m.IsFamily)
			{
				text += "protected ";
			}
			else if (m.IsAssembly)
			{
				text += "internal ";
			}
			else if (m.IsPrivate)
			{
				text += "private ";
			}
			if (m.IsStatic)
			{
				text += "static ";
			}
			else if (m.IsVirtual)
			{
				text = (((m.Attributes & MethodAttributes.VtableLayoutMask) == 0) ? (text + "override ") : (text + "virtual "));
			}
			if (m.IsAbstract)
			{
				text += "abstract ";
			}
			string text2 = "void";
			if (m is MethodInfo methodInfo)
			{
				text2 = methodInfo.ReturnType.FullName ?? methodInfo.ReturnType.Name;
			}
			IEnumerable<string> values = from x in m.GetParameters()
				select (x.ParameterType.FullName ?? x.ParameterType.Name) + " " + x.Name;
			return text + text2 + " " + m.Name + "(" + string.Join(", ", values) + ")";
		}
	}
	public interface IDataExtractor
	{
		string ExtractorName { get; }

		string OutputFileName { get; }

		IEnumerator ExtractData(StreamWriter writer, int maxBytes);

		IEnumerator ExtractDataToZip(StreamWriter writer);
	}
	internal static class ProvenanceWriter
	{
		public const string FileName = "Manifest.json";

		public static JObject Build(DumpManager.DumpOptions options, string baseline)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			JObject val = new JObject();
			val["Type"] = JToken.op_Implicit("Manifest");
			val["TheEyeVersion"] = JToken.op_Implicit("2.2.0");
			val["DumpTimeUtc"] = JToken.op_Implicit(DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture));
			val["Game"] = (JToken)(object)Game();
			val["ManagedAssemblies"] = (JToken)(object)ManagedAssemblies();
			val["BepInEx"] = (JToken)(object)BepInExInfo();
			val["World"] = (JToken)(object)World();
			val["Options"] = (JToken)(object)Options(options, baseline);
			val["Notes"] = (JToken)new JArray(new object[3] { "Accessibility in API_Dump.json is the runtime assembly's. Code compiled against libs-Tools\\assembly_publicizer.dll sees every member as public.", "Valheim stamps every assembly 0.0.0.0; ManagedAssemblies md5 + size is the only reliable build identity.", "ZDO_Dump.json is world state and only diffs meaningfully against a dump of the same world." });
			return val;
		}

		public static string Write(string dumpRoot, JObject manifest)
		{
			string text = Path.Combine(dumpRoot, "Manifest.json");
			File.WriteAllText(text, ((JToken)manifest).ToString((Formatting)1, Array.Empty<JsonConverter>()), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			return text;
		}

		private static JObject Game()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Invalid comparison between Unknown and I4
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			JObject val = new JObject();
			try
			{
				val["VersionString"] = JToken.op_Implicit(Version.GetVersionString(true).Replace("\r", "").Replace("\n", " ")
					.Trim());
			}
			catch (Exception ex)
			{
				val["VersionString"] = JToken.op_Implicit("<" + ex.GetType().Name + ">");
			}
			try
			{
				val["Version"] = JToken.op_Implicit(((object)Version.CurrentVersion/*cast due to .constrained prefix*/).ToString());
			}
			catch
			{
			}
			val["NetworkVersion"] = NetworkVersion();
			val["UnityVersion"] = JToken.op_Implicit(Application.unityVersion);
			val["Platform"] = JToken.op_Implicit(((object)Application.platform/*cast due to .constrained prefix*/).ToString());
			val["Headless"] = JToken.op_Implicit((int)SystemInfo.graphicsDeviceType == 4);
			try
			{
				val["GameRoot"] = JToken.op_Implicit(Paths.GameRootPath);
			}
			catch
			{
			}
			try
			{
				val["ExecutablePath"] = JToken.op_Implicit(Paths.ExecutablePath);
			}
			catch
			{
			}
			val["SteamBuildId"] = SteamBuildId();
			try
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					val["IsServer"] = JToken.op_Implicit(ZNet.instance.IsServer());
					val["IsDedicated"] = JToken.op_Implicit(ZNet.instance.IsDedicated());
				}
			}
			catch
			{
			}
			try
			{
				val["Language"] = JToken.op_Implicit((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : null);
			}
			catch
			{
			}
			return val;
		}

		private static JToken NetworkVersion()
		{
			try
			{
				Type[] array = new Type[2]
				{
					typeof(Version),
					typeof(ZNet)
				};
				foreach (Type type in array)
				{
					FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo in fields)
					{
						if (fieldInfo.Name.IndexOf("etworkVersion", StringComparison.Ordinal) >= 0)
						{
							return JToken.FromObject(fieldInfo.GetValue(null));
						}
					}
					PropertyInfo[] properties = type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (PropertyInfo propertyInfo in properties)
					{
						if (propertyInfo.Name.IndexOf("etworkVersion", StringComparison.Ordinal) >= 0)
						{
							return JToken.FromObject(propertyInfo.GetValue(null, null));
						}
					}
				}
			}
			catch
			{
			}
			return (JToken)(object)JValue.CreateNull();
		}

		private static JToken SteamBuildId()
		{
			try
			{
				string gameRootPath = Paths.GameRootPath;
				string fileName = Path.GetFileName(gameRootPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
				string path = Path.Combine(gameRootPath, "steamapps");
				if (Directory.Exists(path))
				{
					string[] files = Directory.GetFiles(path, "appmanifest_*.acf");
					for (int i = 0; i < files.Length; i++)
					{
						Match match = Regex.Match(File.ReadAllText(files[i]), "\"buildid\"\\s+\"(\\d+)\"");
						if (match.Success)
						{
							return JToken.op_Implicit(match.Groups[1].Value);
						}
					}
				}
				DirectoryInfo directoryInfo = new DirectoryInfo(gameRootPath);
				for (int j = 0; j < 3; j++)
				{
					if (directoryInfo == null)
					{
						break;
					}
					directoryInfo = directoryInfo.Parent;
					if (directoryInfo == null)
					{
						break;
					}
					string[] files = Directory.GetFiles(directoryInfo.FullName, "appmanifest_*.acf");
					for (int i = 0; i < files.Length; i++)
					{
						string input = File.ReadAllText(files[i]);
						Match match2 = Regex.Match(input, "\"installdir\"\\s+\"([^\"]+)\"");
						if (match2.Success && string.Equals(match2.Groups[1].Value, fileName, StringComparison.OrdinalIgnoreCase))
						{
							Match match3 = Regex.Match(input, "\"buildid\"\\s+\"(\\d+)\"");
							if (match3.Success)
							{
								return JToken.op_Implicit(match3.Groups[1].Value);
							}
						}
					}
				}
			}
			catch
			{
			}
			return (JToken)(object)JValue.CreateNull();
		}

		private static JArray ManagedAssemblies()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			JArray val = new JArray();
			try
			{
				string managedPath = Paths.ManagedPath;
				if (!Directory.Exists(managedPath))
				{
					return val;
				}
				using MD5 mD = MD5.Create();
				foreach (string item in Directory.GetFiles(managedPath, "*.dll").OrderBy<string, string>((string f) => Path.GetFileName(f), StringComparer.Ordinal))
				{
					JObject val2 = new JObject();
					val2["Name"] = JToken.op_Implicit(Path.GetFileName(item));
					try
					{
						FileInfo fileInfo = new FileInfo(item);
						val2["Size"] = JToken.op_Implicit(fileInfo.Length);
						val2["LastWriteUtc"] = JToken.op_Implicit(fileInfo.LastWriteTimeUtc.ToString("o", CultureInfo.InvariantCulture));
						using FileStream inputStream = File.OpenRead(item);
						val2["MD5"] = JToken.op_Implicit(BitConverter.ToString(mD.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant());
					}
					catch (Exception ex)
					{
						val2["<error>"] = JToken.op_Implicit(ex.GetType().Name);
					}
					val.Add((JToken)(object)val2);
				}
			}
			catch (Exception ex2)
			{
				WubarrkLogger.Warn("[Eye.Manifest] Managed assembly hashing failed: " + ex2.GetType().Name);
			}
			return val;
		}

		private static JObject BepInExInfo()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			JObject val = new JObject();
			try
			{
				val["Version"] = JToken.op_Implicit(typeof(Paths).Assembly.GetName().Version.ToString());
			}
			catch
			{
			}
			JArray val2 = new JArray();
			try
			{
				foreach (KeyValuePair<string, PluginInfo> item in Chainloader.PluginInfos.OrderBy<KeyValuePair<string, PluginInfo>, string>((KeyValuePair<string, PluginInfo> k) => k.Key, StringComparer.Ordinal))
				{
					JObject val3 = new JObject();
					val3["GUID"] = JToken.op_Implicit(item.Key);
					try
					{
						val3["Name"] = JToken.op_Implicit(item.Value.Metadata.Name);
						val3["Version"] = JToken.op_Implicit(item.Value.Metadata.Version.ToString());
						val3["File"] = JToken.op_Implicit(Path.GetFileName(item.Value.Location ?? ""));
					}
					catch
					{
					}
					val2.Add((JToken)(object)val3);
				}
			}
			catch
			{
			}
			val["Plugins"] = (JToken)(object)val2;
			val["PluginCount"] = JToken.op_Implicit(((JContainer)val2).Count);
			return val;
		}

		private static JObject World()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			JObject val = new JObject();
			try
			{
				World world = ZNet.World;
				val["Loaded"] = JToken.op_Implicit(world != null);
				if (world != null)
				{
					val["Name"] = JToken.op_Implicit(world.m_name);
					val["SeedName"] = JToken.op_Implicit(world.m_seedName);
					val["Seed"] = JToken.op_Implicit(world.m_seed);
					val["UID"] = JToken.op_Implicit(world.m_uid);
					val["WorldVersion"] = JToken.op_Implicit(world.m_worldVersion);
					val["WorldGenVersion"] = JToken.op_Implicit(world.m_worldGenVersion);
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)ZoneSystem.instance != (Object)null)
				{
					val["GlobalKeys"] = (JToken)new JArray((object)ZoneSystem.instance.GetGlobalKeys().OrderBy<string, string>((string k) => k, StringComparer.Ordinal));
				}
			}
			catch
			{
			}
			try
			{
				if (ZDOMan.instance != null)
				{
					val["ZdoCount"] = JToken.op_Implicit(ZDOMan.instance.m_objectsByID.Count);
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					val["PrefabCount"] = JToken.op_Implicit(ZNetScene.instance.m_prefabs.Count);
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					val["ItemCount"] = JToken.op_Implicit(ObjectDB.instance.m_items.Count);
				}
			}
			catch
			{
			}
			try
			{
				val["LocalPlayer"] = JToken.op_Implicit((Object)(object)Player.m_localPlayer != (Object)null);
			}
			catch
			{
			}
			return val;
		}

		private static JObject Options(DumpManager.DumpOptions o, string baseline)
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			return new JObject
			{
				["DumpAgentML"] = JToken.op_Implicit(o.DumpAgentML),
				["DumpAPI"] = JToken.op_Implicit(o.DumpAPI),
				["DumpPrefabs"] = JToken.op_Implicit(o.DumpPrefabs),
				["DumpScene"] = JToken.op_Implicit(o.DumpScene),
				["DumpZDOs"] = JToken.op_Implicit(o.DumpZDOs),
				["DumpObjectDB"] = JToken.op_Implicit(o.DumpObjectDB),
				["DumpValues"] = JToken.op_Implicit(o.DumpValues),
				["DumpCallGraph"] = JToken.op_Implicit(o.DumpCallGraph),
				["DumpRegistry"] = JToken.op_Implicit(o.DumpRegistry),
				["RunHuginnsReport"] = JToken.op_Implicit(o.RunHuginnsReport),
				["Baseline"] = JToken.op_Implicit(baseline),
				["ApiAssemblyFilter"] = JToken.op_Implicit((WubarrkConfig.ApiAssemblyFilter != null) ? WubarrkConfig.ApiAssemblyFilter.Value : null),
				["ZdoIncludeData"] = JToken.op_Implicit(WubarrkConfig.ZdoIncludeData != null && WubarrkConfig.ZdoIncludeData.Value),
				["ForceGlobalActiveArea"] = JToken.op_Implicit(WubarrkConfig.ForceGlobalActiveArea != null && WubarrkConfig.ForceGlobalActiveArea.Value),
				["DumpLocalization"] = JToken.op_Implicit(WubarrkConfig.DumpLocalization != null && WubarrkConfig.DumpLocalization.Value)
			};
		}
	}
	public class RegistryExtractor : IDataExtractor
	{
		public string ExtractorName => "Registries";

		public string OutputFileName => "Registry_Dump.json";

		public IEnumerator ExtractData(StreamWriter writer, int maxBytes)
		{
			return Extract(writer, minifiedJsonl: false);
		}

		public IEnumerator ExtractDataToZip(StreamWriter writer)
		{
			return Extract(writer, minifiedJsonl: true);
		}

		private IEnumerator Extract(StreamWriter writer, bool minifiedJsonl)
		{
			bool isFirst = true;
			int written = 0;
			Dictionary<string, int> seen = new Dictionary<string, int>(StringComparer.Ordinal);
			Action<JObject> emit = delegate(JObject obj)
			{
				string key = (string)obj["_Source"] + "/" + (string)obj["_Key"];
				if (seen.TryGetValue(key, out var value))
				{
					seen[key] = value + 1;
					obj["_Key"] = JToken.op_Implicit((string)obj["_Key"] + "#" + (value + 1));
				}
				else
				{
					seen[key] = 1;
				}
				if (minifiedJsonl)
				{
					writer.WriteLine(((JToken)obj).ToString((Formatting)0, Array.Empty<JsonConverter>()));
				}
				else
				{
					if (!isFirst)
					{
						writer.Write(",\n");
					}
					writer.Write(((JToken)obj).ToString((Formatting)1, Array.Empty<JsonConverter>()));
					isFirst = false;
				}
				written++;
			};
			IEnumerator[] sections = new IEnumerator[10]
			{
				Guard("Enums", Enums(emit)),
				Guard("ZDOVars", ZdoVars(emit)),
				Guard("ConsoleCommands", ConsoleCommands(emit)),
				Gu