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.1.1
plugins/WubarrksEye/WubarrksEye.dll
Decompiled a day 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.Concurrent; 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.Threading.Tasks; using BepInEx; 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.1.1")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "wubarrk.theeye"; public const string PluginName = "Wubarrk's Eye"; public const string PluginVersion = "2.1.1"; 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_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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"); 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>SUCCESS: ZNetScene Area Overrides applied. The Eye is fully open! No ghost ZDOs can hide.</color>"); } catch (Exception ex) { WubarrkLogger.Error("[Eye] FAILED to apply ZNetScene Area Overrides. Exception: " + ex.Message); WubarrkLogger.Warn("[Eye] IMPACT: ZDO dumps may miss objects outside the active player area (Ghost ZDOs). Game will continue to load normally."); } _harmony.PatchAll(); WubarrkLogger.Info("[Eye] General Harmony patches applied."); EyeCommands.Initialize(((BaseUnityPlugin)this).Logger); GameObject val5 = new GameObject("EyeUIManager"); val5.AddComponent<EyeUIManager>(); Object.DontDestroyOnLoad((Object)val5); _log.LogInfo((object)"[Eye] Plugin initialization complete. Wubarrk's Eye is now watching."); } catch (Exception arg) { _log.LogError((object)$"[Eye] Plugin initialization failed: {arg}"); } } private void OnDestroy() { try { if (_harmony != null) { _harmony.UnpatchSelf(); _log.LogInfo((object)"[Eye] Harmony patches unpatched on destroy."); } } catch (Exception arg) { _log.LogError((object)$"[Eye] Failed during OnDestroy: {arg}"); } } } public static class PluginInfo { public const string PLUGIN_GUID = "WubarrksEye"; public const string PLUGIN_NAME = "WubarrksEye"; public const string PLUGIN_VERSION = "2.1.1"; } } 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 ==="); } private static string GetTypeKind(Type t) { if (t.IsInterface) { return "interface"; } if (t.IsEnum) { return "enum"; } if (t.IsValueType) { return "struct"; } return "class"; } private static IEnumerable<Type> GetInheritanceChain(Type t) { while (t != null) { yield return t; t = t.BaseType; } } private static List<string> SafeGetCustomAttributes(MemberInfo m) { try { return (from a in m.GetCustomAttributes(inherit: true) select a.GetType().FullName).ToList(); } catch { return new List<string>(); } } private static string GetFieldModifiers(FieldInfo f) { List<string> list = new List<string>(); list.Add("[" + (f.IsPublic ? "public" : (f.IsFamily ? "protected" : (f.IsAssembly ? "internal" : (f.IsPrivate ? "private" : "unknown"))))); if (f.IsStatic) { list.Add("static"); } if (f.IsInitOnly) { list.Add("readonly"); } if (f.IsLiteral && !f.IsInitOnly) { list.Add("const"); } list.Add("]"); return string.Join(" ", list); } private static string GetPropertyModifiers(PropertyInfo p) { MethodInfo methodInfo = p.GetGetMethod(nonPublic: true) ?? p.GetSetMethod(nonPublic: true); if (!(methodInfo != null)) { return ""; } return GetMethodModifiers(methodInfo); } private static string GetPropertyAccessorFlags(PropertyInfo p) { MethodInfo getMethod = p.GetGetMethod(nonPublic: true); MethodInfo setMethod = p.GetSetMethod(nonPublic: true); if (getMethod == null && setMethod == null) { return ""; } List<string> list = new List<string>(); if (getMethod != null) { list.Add(GetVisibility(getMethod) + " get"); } if (setMethod != null) { list.Add(GetVisibility(setMethod) + " set"); } return "{" + string.Join(", ", list) + "}"; } private static string GetVisibility(MethodBase m) { if (m.IsPublic) { return "public"; } if (m.IsFamily) { return "protected"; } if (m.IsAssembly) { return "internal"; } if (m.IsPrivate) { return "private"; } return "unknown"; } private static string GetMethodModifiers(MethodBase m) { List<string> list = new List<string>(); list.Add("[" + GetVisibility(m)); if (m.IsStatic) { list.Add("static"); } if (m is MethodInfo methodInfo) { if (methodInfo.IsAbstract) { list.Add("abstract"); } else if (methodInfo.IsVirtual && methodInfo.GetBaseDefinition() != methodInfo && !methodInfo.IsFinal) { list.Add("override"); } else if (methodInfo.IsVirtual && !methodInfo.IsAbstract && !methodInfo.IsFinal) { list.Add("virtual"); } } list.Add("]"); return string.Join(" ", list); } private static string FormatFullMethodSignature(MethodInfo m) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(GetMethodModifiers(m)); stringBuilder.Append(' '); stringBuilder.Append(m.ReturnType.FullName); stringBuilder.Append(' '); stringBuilder.Append(m.Name); if (m.IsGenericMethod) { Type[] genericArguments = m.GetGenericArguments(); stringBuilder.Append('<'); stringBuilder.Append(string.Join(", ", genericArguments.Select((Type a) => a.FullName ?? a.Name))); stringBuilder.Append('>'); } stringBuilder.Append('('); ParameterInfo[] parameters = m.GetParameters(); for (int 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", DumpEye); _logger.LogInfo((object)"[Eye/Commands] EyeCommands initialized."); } private static void RegisterCommand(string name, Action<string[]> handler) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) try { new ConsoleCommand(name, "Wubarrk's Eye: " + name, (ConsoleEvent)delegate(ConsoleEventArgs args) { handler(args.Args); }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); _logger.LogInfo((object)("[Eye/Commands] Registered command: " + name)); } catch (Exception arg) { _logger.LogError((object)$"[Eye/Commands] Failed to register command '{name}': {arg}"); } } private static void DumpEye(string[] args) { try { _logger.LogInfo((object)"[Eye/Commands] dump_eye invoked."); string path = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); string dumpRoot = Path.Combine(Paths.ConfigPath, "WubarrksEye_Dumps", path); DumpManager.DumpOptions options = new DumpManager.DumpOptions { DumpAgentML = true, DumpAPI = true, DumpPrefabs = true, DumpScene = true, DumpZDOs = true, DumpObjectDB = true, DumpValues = true, DumpCallGraph = true, RunHuginnsReport = true, HuginnsReportMLFormat = true }; DumpManager.Start(dumpRoot, options); } catch (Exception arg) { _logger.LogError((object)$"[Eye/Commands] dump_eye failed: {arg}"); } } } 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 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; } } } 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 DumpCallGraphOptions = true; public static bool HuginnsReportEnabled = false; public static bool HuginnsReportMLFormat = true; private Rect _windowRect = new Rect(20f, 20f, 450f, 400f); private Rect _hudRect = new Rect(20f, 20f, 300f, 100f); 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() { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); 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 - 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", _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_0328: 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, "AI Agent ML Dump (Complete Consolidated State)", Array.Empty<GUILayoutOption>()); if (DumpAgentMLOptions) { GUILayout.Label("<color=#888888>AI Dump active. Standard dumps disabled.</color>", _labelStyle, Array.Empty<GUILayoutOption>()); } else { DumpApiOptions = GUILayout.Toggle(DumpApiOptions, "Dump API / Types (Reflection)", Array.Empty<GUILayoutOption>()); DumpPrefabsOptions = GUILayout.Toggle(DumpPrefabsOptions, "Dump Prefabs (Detailed)", Array.Empty<GUILayoutOption>()); DumpSceneOptions = GUILayout.Toggle(DumpSceneOptions, "Dump Active Scene Objects", Array.Empty<GUILayoutOption>()); DumpZDOOptions = GUILayout.Toggle(DumpZDOOptions, "Dump ZDO State", 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>()); DumpCallGraphOptions = GUILayout.Toggle(DumpCallGraphOptions, "Dump Call Graph (IL call / field edges)", Array.Empty<GUILayoutOption>()); } GUILayout.Space(10f); GUILayout.Label("<color=#FF5555>Experimental Features</color>", _headerStyle, Array.Empty<GUILayoutOption>()); HuginnsReportEnabled = GUILayout.Toggle(HuginnsReportEnabled, "<color=#FF9999>[EXPERIMENTAL]</color> Enable Huginn's Report (Diff-er)", Array.Empty<GUILayoutOption>()); if (HuginnsReportEnabled) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Toggle(!HuginnsReportMLFormat, "Human Readable", Array.Empty<GUILayoutOption>())) { HuginnsReportMLFormat = false; } if (GUILayout.Toggle(HuginnsReportMLFormat, "AI Agent Format", Array.Empty<GUILayoutOption>())) { HuginnsReportMLFormat = true; } GUILayout.EndHorizontal(); } GUILayout.Space(10f); if (GUILayout.Button("Start Dump", _buttonStyle, Array.Empty<GUILayoutOption>())) { DumpManager.DumpOptions options = new DumpManager.DumpOptions { DumpAgentML = DumpAgentMLOptions, DumpAPI = (DumpAgentMLOptions || DumpApiOptions), DumpPrefabs = (DumpAgentMLOptions || DumpPrefabsOptions), DumpScene = (DumpAgentMLOptions || DumpSceneOptions), DumpZDOs = (DumpAgentMLOptions || DumpZDOOptions), DumpObjectDB = (DumpAgentMLOptions || DumpObjectDBOptions), DumpValues = (DumpAgentMLOptions || DumpValuesOptions), DumpCallGraph = (DumpAgentMLOptions || DumpCallGraphOptions), RunHuginnsReport = HuginnsReportEnabled, HuginnsReportMLFormat = HuginnsReportMLFormat }; string path = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); DumpManager.Start(Path.Combine(Paths.ConfigPath, "WubarrksEye_Dumps", path), options); } } 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 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; } Dictionary<string, List<string>> calledByMap = new Dictionary<string, List<string>>(); 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); } 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) { 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().ToArray(); val2["Callers"] = (JToken)new JArray(array2); writeObj(val2); methodCount++; if (methodCount % batchSize == 0) { writer.Flush(); yield return null; } } writer.Flush(); DumpManager._progress = 100f; WubarrkLogger.Info($"[Eye.CallGraph] {methodCount} records written across {types.Length} types."); 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) { //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_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: 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 item = 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; 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 text2 = 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(text2); val5["Op"] = JToken.op_Implicit(opCode.Name); val2.Add((JToken)(object)val5); if (!calledByMap.TryGetValue(text2, out var value)) { value = (calledByMap[text2] = new List<string>()); } value.Add(item); 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++; } } else 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 text3 = fieldInfo.DeclaringType?.Name + "." + fieldInfo.Name; if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldsfld || opCode == OpCodes.Ldflda || opCode == OpCodes.Ldsflda) { val3.Add(JToken.op_Implicit(text3)); } else if (opCode == OpCodes.Stfld || opCode == OpCodes.Stsfld) { val4.Add(JToken.op_Implicit(text3)); } } } catch { num++; } } else if (opCode.OperandType == OperandType.InlineSwitch) { if (num2 + 4 > iLAsByteArray.Length) { break; } int num3 = BitConverter.ToInt32(iLAsByteArray, num2); num2 += 4; num2 += num3 * 4; } else { switch (opCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.InlineI: case OperandType.InlineSig: case OperandType.InlineString: 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); } public class ValueExtractor : IDataExtractor { internal static class Loc { private static bool _tried; private static object _instance; private static MethodInfo _localize; internal static string Resolve(string token) { if (string.IsNullOrEmpty(token)) { return ""; } if (token[0] != '$') { return token; } if (!_tried) { _tried = true; try { Type type = Type.GetType("Localization, assembly_valheim"); if (type != null) { PropertyInfo property = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public); if (property != null) { _instance = property.GetValue(null, null); } else { FieldInfo field = type.GetField("m_instance", BindingFlags.Static | BindingFlags.NonPublic); if (field != null) { _instance = field.GetValue(null); } } _localize = type.GetMethod("Localize", new Type[1] { typeof(string) }); } } catch { } } if (_instance == null || _localize == null) { return token; } try { return (string)_localize.Invoke(_instance, new object[1] { token }); } catch { return token; } } } internal static class Walker { private sealed class RefComparer : IEqualityComparer<object> { internal static readonly RefComparer Instance = new RefComparer(); public new bool Equals(object a, object b) { return a == b; } public int GetHashCode(object o) { return RuntimeHelpers.GetHashCode(o); } } public const int MaxDepth = 4; public const int MaxCollection = 32; public const int NodeBudget = 25000; private static readonly string[] Forbidden = new string[16] { "PlayFab", "Steamworks", "System.Threading", "System.Net", "System.IO", "System.Reflection", "System.Runtime", "System.Security", "System.Diagnostics", "UnityEngine.Networking", "UnityEngine.AsyncOperation", "UnityEngine.ResourceRequest", "<>", "c__DisplayClass", "d__", "PrivateImplementationDetails" }; private static HashSet<object> _seen; private static int _nodes; private static bool _blown; internal static void Walk(object root, string prefix, JObject w) { if (root != null) { if (_seen == null) { _seen = new HashSet<object>(RefComparer.Instance); } else { _seen.Clear(); } _nodes = 0; _blown = false; try { Recurse(root, prefix, 0, w); } catch (Exception ex) { w[prefix + "<walk-error>"] = JToken.op_Implicit(ex.GetType().Name); } if (_blown) { w[prefix + "<budget-exceeded>"] = JToken.op_Implicit("stopped at " + _nodes + " nodes"); } _seen.Clear(); } } private static void Recurse(object obj, string prefix, int depth, JObject w) { if (obj == null || depth > 4 || _blown) { return; } Type type = obj.GetType(); if (IsForbidden(type)) { return; } foreach (FieldInfo item in Fields(type)) { if (_blown) { break; } object value; try { value = item.GetValue(obj); } catch (Exception ex) { w[prefix + item.Name] = JToken.op_Implicit("<err:" + ex.GetType().Name + ">"); continue; } Emit(value, prefix + item.Name, depth, w); } } private static void Emit(object v, string path, int depth, JObject w) { if (_blown) { return; } if (++_nodes > 25000) { _blown = true; return; } if (v == null) { w[path] = JToken.op_Implicit(""); return; } Type type = v.GetType(); Object val = (Object)((v is Object) ? v : null); if (val != null) { w[path] = JToken.op_Implicit((val == (Object)null) ? "<missing>" : val.name); } else if (IsScalar(type)) { w[path] = JToken.op_Implicit(Scalar(v)); } else if (v is IEnumerable) { bool flag = depth < 3; int num = 0; foreach (object item in (IEnumerable)v) { if (_blown) { return; } if (num >= 32) { w[path + ".<truncated>"] = JToken.op_Implicit("true"); break; } if (flag) { Emit(item, path + "[" + num + "]", depth + 1, w); } else { w[path + "[" + num + "]"] = JToken.op_Implicit(Shallow(item)); } num++; } w[path + ".<count>"] = JToken.op_Implicit(num.ToString(CultureInfo.InvariantCulture)); } else if (depth >= 4 || IsForbidden(type)) { w[path] = JToken.op_Implicit("<" + type.Name + ">"); } else if (!type.IsValueType && !_seen.Add(v)) { w[path] = JToken.op_Implicit("<cycle:" + type.Name + ">"); } else { Recurse(v, path + ".", depth + 1, w); } } private static string Shallow(object e) { if (e == null) { return ""; } Object val = (Object)((e is Object) ? e : null); if (val != null) { if (!(val == (Object)null)) { return val.name; } return "<missing>"; } Type type = e.GetType(); if (!IsScalar(type)) { return "<" + type.Name + ">"; } return Scalar(e); } private static IEnumerable<FieldInfo> Fields(Type t) { try { return t.GetFields(BindingFlags.Instance | BindingFlags.Public); } catch { return new FieldInfo[0]; } } private static bool IsScalar(Type t) { if (!t.IsPrimitive && !t.IsEnum && !(t == typeof(string)) && !(t == typeof(decimal)) && !(t == typeof(DateTime)) && !(t == typeof(Vector2)) && !(t == typeof(Vector3)) && !(t == typeof(Vector4)) && !(t == typeof(Quaternion)) && !(t == typeof(Color))) { return t == typeof(Color32); } return true; } private static string Scalar(object v) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) if (v is string) { return (string)v; } if (v is float num) { return num.ToString("R", CultureInfo.InvariantCulture); } if (v is double num2) { return num2.ToString("R", CultureInfo.InvariantCulture); } if (v is bool) { if (!(bool)v) { return "false"; } return "true"; } if (v is Enum) { return v.ToString(); } if (v is Vector2 val) { return F(val.x) + "," + F(val.y); } if (v is Vector3 val2) { return F(val2.x) + "," + F(val2.y) + "," + F(val2.z); } if (v is Vector4 val3) { return F(val3.x) + "," + F(val3.y) + "," + F(val3.z) + "," + F(val3.w); } if (v is Quaternion val4) { return F(val4.x) + "," + F(val4.y) + "," + F(val4.z) + "," + F(val4.w); } if (v is Color val5) { return F(val5.r) + "," + F(val5.g) + "," + F(val5.b) + "," + F(val5.a); } if (v is Color32 val6) { return val6.r + "," + val6.g + "," + val6.b + "," + val6.a; } return Convert.ToString(v, CultureInfo.InvariantCulture); } private static string F(float f) { return f.ToString("R", CultureInfo.InvariantCulture); } private static bool IsForbidden(Type t) { string text = t.FullName ?? t.Name; for (int i = 0; i < Forbidden.Length; i++) { if (text.IndexOf(Forbidden[i], StringComparison.Ordinal) >= 0) { return true; } } return false; } internal static string NameOf(object o, params string[] candidates) { Type type = o.GetType(); foreach (string name in candidates) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field == null) { continue; } object value; try { value = field.GetValue(o); } catch { continue; } if (value == null) { continue; } Object val = (Object)((value is Object) ? value : null); if (val != null) { if (val != (Object)null) { return val.name; } continue; } string text = value as string; if (!string.IsNullOrEmpty(text)) { return text; } } return type.Name; } } public string ExtractorName => "Values"; public string OutputFileName => "Values_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) { bool isFirst = true; int n; if ((Object)(object)ObjectDB.instance != (Object)null) { ObjectDB db = ObjectDB.instance; if (db.m_items != null && db.m_items.Count > 0) { n = 0; foreach (GameObject item in db.m_items) { if (DumpManager._cancelRequested) { yield break; } if ((Object)(object)item != (Object)null) { ItemDrop component = item.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { JObject val = new JObject(); val["_Key"] = JToken.op_Implicit(((Object)item).name); val["_Source"] = JToken.op_Implicit("Items"); val["_components"] = JToken.op_Implicit(string.Join("|", from c in item.GetComponents<Component>() where (Object)(object)c != (Object)null select ((object)c).GetType().Name)); SharedData val2 = ((component.m_itemData != null) ? component.m_itemData.m_shared : null); if (val2 != null) { val["_displayName"] = JToken.op_Implicit(Loc.Resolve(val2.m_name)); val["_displayDesc"] = JToken.op_Implicit(Loc.Resolve(val2.m_description)); } Walker.Walk(component.m_itemData, "", val); writeObj(val); } } int num = n + 1; n = num; if (num % 10 == 0) { yield return null; } } } if (db.m_recipes != null && db.m_recipes.Count > 0) { n = 0; foreach (Recipe recipe in db.m_recipes) { if (!DumpManager._cancelRequested) { if ((Object)(object)recipe != (Object)null) { JObject val3 = new JObject(); val3["_Key"] = JToken.op_Implicit(((Object)(object)recipe.m_item != (Object)null && (Object)(object)((Component)recipe.m_item).gameObject != (Object)null) ? ((Object)((Component)recipe.m_item).gameObject).name : ((Object)recipe).name); val3["_Source"] = JToken.op_Implicit("Recipes"); Walker.Walk(recipe, "", val3); writeObj(val3); } int num = n + 1; n = num; if (num % 10 == 0) { yield return null; } continue; } yield break; } } if (db.m_StatusEffects != null && db.m_StatusEffects.Count > 0) { n = 0; foreach (StatusEffect statusEffect in db.m_StatusEffects) { if (!DumpManager._cancelRequested) { if ((Object)(object)statusEffect != (Object)null) { JObject val4 = new JObject(); val4["_Key"] = JToken.op_Implicit(((Object)statusEffect).name); val4["_Source"] = JToken.op_Implicit("StatusEffects"); val4["_displayName"] = JToken.op_Implicit(Loc.Resolve(statusEffect.m_name)); val4["_class"] = JToken.op_Implicit(((object)statusEffect).GetType().Name); Walker.Walk(statusEffect, "", val4); writeObj(val4); } int num = n + 1; n = num; if (num % 10 == 0) { yield return null; } continue; } yield break; } } } if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null && ZNetScene.instance.m_prefabs.Count > 0) { Assembly valheim = typeof(ZNetScene).Assembly; n = 0; foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (DumpManager._cancelRequested) { yield break; } if ((Object)(object)prefab != (Object)null) { JObject val5 = new JObject(); val5["_Key"] = JToken.op_Implicit(((Object)prefab).name); val5["_Source"] = JToken.op_Implicit("Prefabs"); Component[] array = null; try { array = prefab.GetComponents<Component>(); } catch { } if (array != null) { val5["_components"] = JToken.op_Implicit(string.Join("|", from c in array where (Object)(object)c != (Object)null select ((object)c).GetType().Name)); List<string> list = new List<string>(); int childCount = prefab.transform.childCount; for (int num2 = 0; num2 < childCount && num2 < 32; num2++) { list.Add(((Object)prefab.transform.GetChild(num2)).name); } if (list.Count > 0) { val5["_children"] = JToken.op_Implicit(string.Join("|", list)); } Component[] array2 = array; foreach (Component val6 in array2) { if (!((Object)(object)val6 == (Object)null)) { Type type = ((object)val6).GetType(); if (!(type.Assembly != valheim)) { Walker.Walk(val6, type.Name + ".", val5); } } } } writeObj(val5); } int num = n + 1; n = num; if (num % 10 == 0) { yield return null; } } } if (!((Object)(object)ZoneSystem.instance != (Object)null)) { yield break; } if (ZoneSystem.instance.m_vegetation != null && ZoneSystem.instance.m_vegetation.Count > 0) { n = 0; foreach (ZoneVegetation item2 in ZoneSystem.instance.m_vegetation) { if (!DumpManager._cancelRequested) { if (item2 != null) { JObject val7 = new JObject(); val7["_Key"] = JToken.op_Implicit(Walker.NameOf(item2, "m_name", "m_prefab")); val7["_Source"] = JToken.op_Implicit("Vegetation"); Walker.Walk(item2, "", val7); writeObj(val7); } int num = n + 1; n = num; if (num % 10 == 0) { yield return null; } continue; } yield break; } } if (ZoneSystem.instance.m_locations == null || ZoneSystem.instance.m_locations.Count <= 0) { yield break; } n = 0; foreach (ZoneLocation location in ZoneSystem.instance.m_locations) { if (!DumpManager._cancelRequested) { if (location != null) { JObject val8 = new JObject(); val8["_Key"] = JToken.op_Implicit(Walker.NameOf(location, "m_prefabName", "m_prefab")); val8["_Source"] = JToken.op_Implicit("Locations"); Walker.Walk(location, "", val8); writeObj(val8); } int num = n + 1; n = num; if (num % 10 == 0) { yield return null; } continue; } yield break; } void writeObj(JObject val9) { if (minifiedJsonl) { writer.WriteLine(((JToken)val9).ToString((Formatting)0, Array.Empty<JsonConverter>())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val9).ToString((Formatting)1, Array.Empty<JsonConverter>())); isFirst = false; } } } } } namespace WubarrksEye.Core.Commands { public class CoroutineRunner : MonoBehaviour { private static CoroutineRunner _instance; [RuntimeInitializeOnLoadMethod] private static void Init() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (!((Object)_instance != (Object)null)) { GameObject val = new GameObject("Wubarrk_CoroutineRunner"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent<CoroutineRunner>(); } } public static void Run(IEnumerator routine) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown if ((Object)_instance == (Object)null) { Init(); } ((MonoBehaviour)_instance).StartCoroutine(routine); } } public static class DumpManager { public struct DumpOptions { public bool DumpAgentML; public bool DumpAPI; public bool DumpPrefabs; public bool DumpScene; public bool DumpZDOs; public bool DumpObjectDB; public bool DumpValues; public bool DumpCallGraph; public bool RunHuginnsReport; public bool HuginnsReportMLFormat; } private class ApiExtractor : IDataExtractor { 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); } private IEnumerator Extract(StreamWriter writer, bool minifiedJsonl) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); List<Type> allTypes = new List<Type>(); Assembly[] array = assemblies; foreach (Assembly assembly in array) { try { allTypes.AddRange(assembly.GetTypes()); } catch { } } int totalTypes = allTypes.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 j = 0; j < totalTypes; j += batchSize) { if (_cancelRequested) { break; } List<Type> chunk = allTypes.Skip(j).Take(batchSize).ToList(); ConcurrentQueue<JObject> results = new ConcurrentQueue<JObject>(); Task.Run(delegate { Parallel.ForEach(chunk, new ParallelOptions { MaxDegreeOfParallelism = 2 }, delegate(Type t) { try { results.Enqueue(DumpTypeInfo(t)); } catch { } }); }).Wait(); foreach (JObject item in results) { if (minifiedJsonl) { writer.WriteLine(((JToken)item).ToString((Formatting)0, Array.Empty<JsonConverter>())); continue; } if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)item).ToString((Formatting)1, Array.Empty<JsonConverter>())); isFirst = false; } _progress = (float)j / (float)totalTypes * 100f; yield return null; } } private JObject DumpTypeInfo(Type t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown JObject val = new JObject(); if (t == null) { return val; } val["Type"] = JToken.op_Implicit("API_Type"); val["FullName"] = JToken.op_Implicit(t.FullName); val["Namespace"] = JToken.op_Implicit(t.Namespace); val["Kind"] = JToken.op_Implicit(t.IsInterface ? "interface" : (t.IsEnum ? "enum" : (t.IsValueType ? "struct" : "class"))); val["BaseType"] = JToken.op_Implicit(t.BaseType?.FullName); MethodInfo[] methods = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (methods.Length != 0) { JArray val2 = new JArray(); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { JObject val3 = new JObject(); val3["Name"] = JToken.op_Implicit(methodInfo.Name); val3["ReturnType"] = JToken.op_Implicit(methodInfo.ReturnType.FullName); val2.Add((JToken)(object)val3); } val["Methods"] = (JToken)(object)val2; } return val; } } private class PrefabExtractor : IDataExtractor { public string ExtractorName => "Prefabs"; public string OutputFileName => "Prefabs_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) { if ((Object)(object)ZNetScene.instance == (Object)null) { yield break; } List<GameObject> prefabs = ZNetScene.instance.m_prefabs; int total = prefabs.Count; int num = 1; if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_32GB) { num = 3; } if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_64GB_Plus) { num = 10; } int batchSize = WubarrkConfig.BurstObjectsPerFrame.Value * num; if (batchSize <= 0) { batchSize = 10; } bool isFirst = true; for (int i = 0; i < total; i++) { if (_cancelRequested) { break; } GameObject val = prefabs[i]; if ((Object)(object)val != (Object)null) { JObject val2 = DumpGameObjectData(val); if (minifiedJsonl) { writer.WriteLine(((JToken)val2).ToString((Formatting)0, Array.Empty<JsonConverter>())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val2).ToString((Formatting)1, Array.Empty<JsonConverter>())); isFirst = false; } } if (i % batchSize == 0) { _progress = (float)i / (float)total * 100f; yield return null; } } } } private class SceneExtractor : IDataExtractor { public string ExtractorName => "Scene Objects"; public string OutputFileName => "Scene_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) { Scene activeScene = SceneManager.GetActiveScene(); GameObject[] rootObjects = (GameObject[])(((Scene)(ref activeScene)).IsValid() ? ((Array)((Scene)(ref activeScene)).GetRootGameObjects()) : ((Array)new GameObject[0])); int num = 1; if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_32GB) { num = 3; } if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_64GB_Plus) { num = 10; } int batchSize = WubarrkConfig.BurstObjectsPerFrame.Value * num; if (batchSize <= 0) { batchSize = 10; } bool isFirst = true; int count = 0; GameObject[] array = rootObjects; foreach (GameObject val in array) { if (_cancelRequested) { break; } if ((Object)(object)val != (Object)null) { JObject val2 = DumpGameObjectData(val); if (minifiedJsonl) { writer.WriteLine(((JToken)val2).ToString((Formatting)0, Array.Empty<JsonConverter>())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val2).ToString((Formatting)1, Array.Empty<JsonConverter>())); isFirst = false; } } count++; if (count % batchSize == 0) { _progress = (float)count / (float)rootObjects.Length * 100f; yield return null; } } } } private class ZdoExtractor : IDataExtractor { public string ExtractorName => "ZDO State"; public string OutputFileName => "ZDO_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) { if (ZDOMan.instance == null) { yield break; } List<ZDO> zdos = ZDOMan.instance.m_objectsByID.Values.ToList(); int total = zdos.Count; int num = 1; if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_32GB) { num = 3; } if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_64GB_Plus) { num = 10; } int batchSize = WubarrkConfig.BurstObjectsPerFrame.Value * 5 * num; if (batchSize <= 0) { batchSize = 50; } bool isFirst = true; for (int i = 0; i < total; i++) { if (_cancelRequested) { break; } ZDO val = zdos[i]; if (val != null) { JObject val2 = new JObject(); val2["Type"] = JToken.op_Implicit("ZDO"); val2["UID"] = JToken.op_Implicit(((object)Unsafe.As<ZDOID, ZDOID>(ref val.m_uid)/*cast due to .constrained prefix*/).ToString()); try { val2["Owner"] = JToken.op_Implicit(val.GetOwner()); } catch { } val2["Prefab"] = JToken.op_Implicit(val.GetPrefab()); val2["Position"] = JToken.op_Implicit(((object)val.GetPosition()/*cast due to .constrained prefix*/).ToString()); if (minifiedJsonl) { writer.WriteLine(((JToken)val2).ToString((Formatting)0, Array.Empty<JsonConverter>())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val2).ToString((Formatting)1, Array.Empty<JsonConverter>())); isFirst = false; } } if (i % batchSize == 0) { _progress = (float)i / (float)total * 100f; yield return null; } } } } private class ObjectDbExtractor : IDataExtractor { public string ExtractorName => "ObjectDB"; public string OutputFileName => "ObjectDB_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) { if ((Object)(object)ObjectDB.instance == (Object)null) { yield break; } bool isFirst = true; List<GameObject> items = ObjectDB.instance.m_items; int count = 0; foreach (GameObject item in items) { if (_cancelRequested) { break; } if ((Object)(object)item != (Object)null) { JObject val = DumpGameObjectData(item); 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; } } count++; if (count % 10 == 0) { yield return null; } } } } private static bool _isRunning; internal static bool _cancelRequested; internal static float _progress; private static float _overallProgress; private static string _currentPhase = ""; public static bool IsRunning => _isRunning; public static float ProgressPercentage => _progress; public static float OverallProgress => _overallProgress; public static string CurrentPhase => _currentPhase; public static void Start(string dumpRoot, DumpOptions options) { if (!_isRunning) { _isRunning = true; _cancelRequested = false; _progress = 0f; _overallProgress = 0f; _currentPhase = "Initializing"; Directory.CreateDirectory(dumpRoot); CoroutineRunner.Run(DumpRoutine(dumpRoot, options)); } } public static void Cancel() { _cancelRequested = true; } private static IEnumerator DumpRoutine(string dumpRoot, DumpOptions options) { try { WubarrkLogger.Info("[Eye.Deep] Streaming Dump started in " + dumpRoot); int maxBytes = WubarrkConfig.DumpMaxFileSizeMB.Value * 1024 * 1024; if (maxBytes <= 0) { maxBytes = 1073741824; } List<IDataExtractor> activeExtractors = new List<IDataExtractor>(); if (options.DumpAPI) { activeExtractors.Add(new ApiExtractor()); } if (options.DumpPrefabs) { activeExtractors.Add(new PrefabExtractor()); } if (options.DumpScene) { activeExtractors.Add(new SceneExtractor()); } if (options.DumpZDOs) { activeExtractors.Add(new ZdoExtractor()); } if (options.DumpObjectDB) { activeExtractors.Add(new ObjectDbExtractor()); } if (options.DumpValues) { activeExtractors.Add(new ValueExtractor()); } if (options.DumpCallGraph) { activeExtractors.Add(new CallGraphExtractor()); } int passes = (options.DumpAgentML ? 1 : 0) + 1; int passIndex = 0; for (int i = 0; i < activeExtractors.Count; i++) { if (_cancelRequested) { break; } IDataExtractor extractor = activeExtractors[i]; _currentPhase = "Standard: " + extractor.ExtractorName; _progress = 0f; string path = Path.Combine(dumpRoot, extractor.OutputFileName); using (StreamWriter writer = new StreamWriter(path, append: false, Encoding.UTF8)) { writer.Write("[\n"); IEnumerator extRoutine = null; try { extRoutine = extractor.ExtractData(writer, maxBytes); } catch (Exception arg) { WubarrkLogger.Error($"[Eye.Deep] {extractor.ExtractorName} failed to start: {arg}"); } while (extRoutine != null) { bool flag; try { flag = extRoutine.MoveNext(); } catch (Exception arg2) { WubarrkLogger.Error($"[Eye.Deep] {extractor.ExtractorName} aborted: {arg2}"); break; } if (!flag) { break; } _overallProgress = ((float)passIndex * 100f + ((float)i * 100f + _progress) / (float)activeExtractors.Count) / (float)passes; yield return extRoutine.Current; } writer.Write("\n]"); } WubarrkLogger.Info("[Eye.Deep] Wrote " + extractor.OutputFileName); } passIndex++; if (options.DumpAgentML && !_cancelRequested) { _currentPhase = "Building AI Agent ML Dump (.zip)"; string path2 = Path.Combine(dumpRoot, "AgentML_Complete_Dump.zip"); using FileStream fs = new FileStream(path2, FileMode.Create); using ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Create); ZipArchiveEntry zipArchiveEntry = archive.CreateEntry("AgentML_Complete_Dump.jsonl", CompressionLevel.Optimal); using StreamWriter writer = new StreamWriter(zipArchiveEntry.Open()); for (int i = 0; i < activeExtractors.Count; i++) { if (_cancelRequested) { break; } IDataExtractor extractor = activeExtractors[i]; _currentPhase = "ML: " + extractor.ExtractorName; _progress = 0f; IEnumerator extRoutine = null; try { extRoutine = extractor.ExtractDataToZip(writer); } catch (Exception arg3) { WubarrkLogger.Error($"[Eye.Deep] {extractor.ExtractorName} (ML) failed to start: {arg3}"); } while (extRoutine != null) { bool flag2; try { flag2 = extRoutine.MoveNext(); } catch (Exception arg4) { WubarrkLogger.Error($"[Eye.Deep] {extractor.ExtractorName} (ML) aborted: {arg4}"); break; } if (!flag2) { break; } _overallProgress = ((float)passIndex * 100f + ((float)i * 100f + _progress) / (float)activeExtractors.Count) / (float)passes; yield return extRoutine.Current; } } } if (options.RunHuginnsReport && !_cancelRequested) { _currentPhase = "Huginn's Report (Diffing)"; _progress = 0f; _overallProgress = 99f; yield return HuginnsReport.RunDiff(dumpRoot, options); } _progress = 100f; _overallProgress = 100f; _currentPhase = (_cancelRequested ? "Cancelled" : "Complete"); WubarrkLogger.Info(_cancelRequested ? "[Eye.Deep] Dump cancelled." : ("[Eye.Deep] Dump completed successfully. Output: " + dumpRoot)); } finally { _isRunning = false; } } private static JObject DumpGameObjectData(GameObject go) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown JObject val = new JObject(); val["Type"] = JToken.op_Implicit("GameObject"); val["Name"] = JToken.op_Implicit(((Object)go).name); Component[] components = go.GetComponents<Component>(); JArray val2 = new JArray(); Component[] array = components; foreach (Component val3 in array) { if (!((Object)(object)val3 == (Object)null)) { JObject val4 = new JObject(); val4["ComponentType"] = JToken.op_Implicit(((object)val3).GetType().FullName); ZNetView val5 = (ZNetView)(object)((val3 is ZNetView) ? val3 : null); if ((Object)(object)val5 != (Object)null) { val4["PrefabHash"] = JToken.op_Implicit(val5.GetPrefabName().GetHashCode()); } val2.Add((JToken)(object)val4); } } val["Components"] = (JToken)(object)val2; return val; } } public static class HuginnsReport { public static IEnumerator RunDiff(string currentDumpRoot, DumpManager.DumpOptions options) { WubarrkLogger.Info("[Huginn] Preparing to execute Huginn's Report (Diff-er)..."); DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Paths.ConfigPath, "WubarrksEye_Dumps")); if (!directoryInfo.Exists) { yield break; } List<DirectoryInfo> list = (from d in directoryInfo.GetDirectories() where d.FullName != currentDumpRoot orderby d.CreationTime descending select d).ToList(); string previousDumpRoot = null; foreach (DirectoryInfo item in list) { if (options.DumpAgentML) { if (File.Exists(Path.Combine(item.FullName, "AgentML_Complete_Dump.zip"))) {