Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of The Eye v2.2.0
plugins/WubarrksEye/WubarrksEye.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.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