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 { 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 _visited = new HashSet(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 onField) { _visited.Clear(); _count = 0; WalkInternal(root, "root", 0, onField); } private static void WalkInternal(object obj, string path, int depth, Action 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 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] SUCCESS: ZNetScene Area Overrides applied. The Eye is fully open! No ghost ZDOs can hide."); } 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(); 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 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 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 ?? "")); 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(""); } 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(""); } else { foreach (Type item2 in interfaces.OrderBy((Type type3) => type3.FullName)) { w.WriteLine(item2.FullName); } } w.WriteLine("Attributes:"); List list = SafeGetCustomAttributes(type); if (list.Count == 0) { w.WriteLine(""); } 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(""); } w.WriteLine("Fields:"); FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fields.Length == 0) { w.WriteLine(""); } 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(""); } 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(""); } 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(""); } 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().ToArray(); if (array5.Length == 0) { w.WriteLine(""); } 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 GetInheritanceChain(Type t) { while (t != null) { yield return t; t = t.BaseType; } } private static List SafeGetCustomAttributes(MemberInfo m) { try { return (from a in m.GetCustomAttributes(inherit: true) select a.GetType().FullName).ToList(); } catch { return new List(); } } private static string GetFieldModifiers(FieldInfo f) { List list = new List(); 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 list = new List(); 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 list = new List(); 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 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 EnableMod; public static ConfigEntry PhysicsAuthorityMode; public static ConfigEntry DumpMaxFileSizeMB; public static ConfigEntry DeepDiagnostics; public static ConfigEntry BurstObjectsPerFrame; public static ConfigEntry SystemMemoryProfile; public static ConfigEntry DifferThreadCount; public static void Bind(ConfigFile Config) { EnableMod = Config.Bind("Core", "EnableMod", true, "Turns the mod on or off. Leave this on unless you're troubleshooting."); PhysicsAuthorityMode = Config.Bind("Core", "PhysicsAuthorityMode", "server", "Who controls physics: the server or the client. If you don't know, leave it alone."); DumpMaxFileSizeMB = Config.Bind("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("Diagnostics", "DeepDiagnostics", false, "Extra logging and extra detail. Helps debugging. Slows things down."); BurstObjectsPerFrame = Config.Bind("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("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("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 "" + message + ""; } if (message.Contains("[Error]")) { return "" + message + ""; } 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()); 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()); } else { GUILayout.Label("Waiting for game...", _labelStyle, Array.Empty()); } if (DumpManager.IsRunning) { GUILayout.Label($"Total Progress: {DumpManager.OverallProgress:F1}%", _labelStyle, Array.Empty()); GUILayout.Label($"Phase: {DumpManager.CurrentPhase} ({DumpManager.ProgressPercentage:F0}%)", _labelStyle, Array.Empty()); } else { GUILayout.Label("Status: Idle", _labelStyle, Array.Empty()); } 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()); if (DumpManager.IsRunning) { GUILayout.Label($"Total Progress: {DumpManager.OverallProgress:F1}%", _labelStyle, Array.Empty()); GUILayout.Label($"Phase: {DumpManager.CurrentPhase} ({DumpManager.ProgressPercentage:F0}%)", _labelStyle, Array.Empty()); if (GUILayout.Button("Cancel Dump", _buttonStyle, Array.Empty())) { DumpManager.Cancel(); } } else { DumpAgentMLOptions = GUILayout.Toggle(DumpAgentMLOptions, "AI Agent ML Dump (Complete Consolidated State)", Array.Empty()); if (DumpAgentMLOptions) { GUILayout.Label("AI Dump active. Standard dumps disabled.", _labelStyle, Array.Empty()); } else { DumpApiOptions = GUILayout.Toggle(DumpApiOptions, "Dump API / Types (Reflection)", Array.Empty()); DumpPrefabsOptions = GUILayout.Toggle(DumpPrefabsOptions, "Dump Prefabs (Detailed)", Array.Empty()); DumpSceneOptions = GUILayout.Toggle(DumpSceneOptions, "Dump Active Scene Objects", Array.Empty()); DumpZDOOptions = GUILayout.Toggle(DumpZDOOptions, "Dump ZDO State", Array.Empty()); DumpObjectDBOptions = GUILayout.Toggle(DumpObjectDBOptions, "Dump ObjectDB (Items & Recipes)", Array.Empty()); DumpValuesOptions = GUILayout.Toggle(DumpValuesOptions, "Dump Values (field contents)", Array.Empty()); DumpCallGraphOptions = GUILayout.Toggle(DumpCallGraphOptions, "Dump Call Graph (IL call / field edges)", Array.Empty()); } GUILayout.Space(10f); GUILayout.Label("Experimental Features", _headerStyle, Array.Empty()); HuginnsReportEnabled = GUILayout.Toggle(HuginnsReportEnabled, "[EXPERIMENTAL] Enable Huginn's Report (Diff-er)", Array.Empty()); if (HuginnsReportEnabled) { GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Toggle(!HuginnsReportMLFormat, "Human Readable", Array.Empty())) { HuginnsReportMLFormat = false; } if (GUILayout.Toggle(HuginnsReportMLFormat, "AI Agent Format", Array.Empty())) { HuginnsReportMLFormat = true; } GUILayout.EndHorizontal(); } GUILayout.Space(10f); if (GUILayout.Button("Start Dump", _buttonStyle, Array.Empty())) { 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> calledByMap = new Dictionary>(); 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 list; try { list = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Cast().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> 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()); 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> 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()); } 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 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 { 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 _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(RefComparer.Instance); } else { _seen.Clear(); } _nodes = 0; _blown = false; try { Recurse(root, prefix, 0, w); } catch (Exception ex) { w[prefix + ""] = JToken.op_Implicit(ex.GetType().Name); } if (_blown) { w[prefix + ""] = 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(""); 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) ? "" : 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 + "."] = 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 + "."] = 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(""); } 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 ""; } Type type = e.GetType(); if (!IsScalar(type)) { return "<" + type.Name + ">"; } return Scalar(e); } private static IEnumerable 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(); 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() 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(); } 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 list = new List(); 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())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val9).ToString((Formatting)1, Array.Empty())); 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(); } } 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 allTypes = new List(); 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 chunk = allTypes.Skip(j).Take(batchSize).ToList(); ConcurrentQueue results = new ConcurrentQueue(); 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())); continue; } if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)item).ToString((Formatting)1, Array.Empty())); 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 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())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val2).ToString((Formatting)1, Array.Empty())); 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())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val2).ToString((Formatting)1, Array.Empty())); 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 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(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())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val2).ToString((Formatting)1, Array.Empty())); 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 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())); } else { if (!isFirst) { writer.Write(",\n"); } writer.Write(((JToken)val).ToString((Formatting)1, Array.Empty())); 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 activeExtractors = new List(); 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(); 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 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"))) { previousDumpRoot = item.FullName; break; } } else if (File.Exists(Path.Combine(item.FullName, "Prefabs_Dump.json")) || File.Exists(Path.Combine(item.FullName, "ZDO_Dump.json"))) { previousDumpRoot = item.FullName; break; } } if (previousDumpRoot == null) { WubarrkLogger.Info("[Huginn] No previous dump of the same format found to compare against."); yield break; } WubarrkLogger.Info("[Huginn] Comparing against previous dump: " + previousDumpRoot); Task diffTask = Task.Run(delegate { ExecuteDiff(previousDumpRoot, currentDumpRoot, options); }); while (!diffTask.IsCompleted) { yield return null; } if (diffTask.IsFaulted) { WubarrkLogger.Error($"[Huginn] Diff failed: {diffTask.Exception}"); } else { WubarrkLogger.Info("[Huginn] Report completed successfully."); } } private static void ExecuteDiff(string oldRoot, string newRoot, DumpManager.DumpOptions options) { string text = (options.HuginnsReportMLFormat ? ".jsonl" : ".json"); using StreamWriter streamWriter = new StreamWriter(Path.Combine(newRoot, "Huginn_Diff_Report" + text), append: false); if (!options.HuginnsReportMLFormat) { streamWriter.Write("[\n"); } if (options.DumpAgentML) { DiffZipArchives(oldRoot, newRoot, streamWriter, options.HuginnsReportMLFormat); } else { DiffStandardJson(oldRoot, newRoot, streamWriter, options.HuginnsReportMLFormat); } if (!options.HuginnsReportMLFormat) { streamWriter.Write("\n]"); } } private static void DiffZipArchives(string oldRoot, string newRoot, StreamWriter writer, bool mlFormat) { string path = Path.Combine(oldRoot, "AgentML_Complete_Dump.zip"); string path2 = Path.Combine(newRoot, "AgentML_Complete_Dump.zip"); if (!File.Exists(path) || !File.Exists(path2)) { return; } HashSet hashSet = new HashSet(); using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { using ZipArchive zipArchive = new ZipArchive(stream, ZipArchiveMode.Read); ZipArchiveEntry zipArchiveEntry = zipArchive.Entries.FirstOrDefault((ZipArchiveEntry e) => e.Name.EndsWith(".jsonl")); if (zipArchiveEntry != null) { using StreamReader streamReader = new StreamReader(zipArchiveEntry.Open()); string input; while ((input = streamReader.ReadLine()) != null) { hashSet.Add(GetHashString(input)); } } } ConcurrentQueue concurrentQueue = new ConcurrentQueue(); int num = 1000; if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_32GB) { num = 5000; } if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_64GB_Plus) { num = 20000; } bool flag = true; using FileStream stream2 = new FileStream(path2, FileMode.Open, FileAccess.Read); using ZipArchive zipArchive2 = new ZipArchive(stream2, ZipArchiveMode.Read); ZipArchiveEntry zipArchiveEntry2 = zipArchive2.Entries.FirstOrDefault((ZipArchiveEntry e) => e.Name.EndsWith(".jsonl")); if (zipArchiveEntry2 == null) { return; } using StreamReader streamReader2 = new StreamReader(zipArchiveEntry2.Open()); List list = new List(); string item; while ((item = streamReader2.ReadLine()) != null) { list.Add(item); if (list.Count <= num) { continue; } ProcessChunks(list, hashSet, concurrentQueue, mlFormat); list.Clear(); string result; while (concurrentQueue.TryDequeue(out result)) { if (!mlFormat && !flag) { writer.Write(",\n"); } writer.WriteLine(result); flag = false; } } if (list.Count <= 0) { return; } ProcessChunks(list, hashSet, concurrentQueue, mlFormat); string result2; while (concurrentQueue.TryDequeue(out result2)) { if (!mlFormat && !flag) { writer.Write(",\n"); } writer.WriteLine(result2); flag = false; } } private static void DiffStandardJson(string oldRoot, string newRoot, StreamWriter writer, bool mlFormat) { string[] files = Directory.GetFiles(newRoot, "*.json"); int num = 1000; if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_32GB) { num = 5000; } if (WubarrkConfig.SystemMemoryProfile.Value == WubarrkConfig.RamProfile.Rig_64GB_Plus) { num = 20000; } bool flag = true; string[] array = files; foreach (string path in array) { string path2 = Path.Combine(oldRoot, Path.GetFileName(path)); if (!File.Exists(path2)) { continue; } HashSet hashSet = new HashSet(); foreach (string item in File.ReadLines(path2)) { hashSet.Add(GetHashString(item.Trim())); } List list = new List(); ConcurrentQueue concurrentQueue = new ConcurrentQueue(); foreach (string item2 in File.ReadLines(path)) { list.Add(item2); if (list.Count <= num) { continue; } ProcessChunks(list, hashSet, concurrentQueue, mlFormat); list.Clear(); string result; while (concurrentQueue.TryDequeue(out result)) { if (!mlFormat && !flag) { writer.Write(",\n"); } writer.WriteLine(result); flag = false; } } if (list.Count <= 0) { continue; } ProcessChunks(list, hashSet, concurrentQueue, mlFormat); string result2; while (concurrentQueue.TryDequeue(out result2)) { if (!mlFormat && !flag) { writer.Write(",\n"); } writer.WriteLine(result2); flag = false; } } } private static void ProcessChunks(List lines, HashSet oldHashes, ConcurrentQueue outputLines, bool mlFormat) { int num = WubarrkConfig.DifferThreadCount.Value; if (num < 1) { num = 1; } Parallel.ForEach(lines, new ParallelOptions { MaxDegreeOfParallelism = num }, delegate(string line) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown string text = line.Trim(); if (!string.IsNullOrEmpty(text)) { switch (text) { case "]": break; case "{": break; case "}": break; default: { string hashString = GetHashString(text); if (!oldHashes.Contains(hashString)) { JObject val = new JObject(); val["Change"] = JToken.op_Implicit("ADDED_OR_MODIFIED"); try { val["Data"] = (JToken)(object)JObject.Parse(text.EndsWith(",") ? text.Substring(0, text.Length - 1) : text); } catch { val["Data"] = JToken.op_Implicit(text); } if (mlFormat) { outputLines.Enqueue(((JToken)val).ToString((Formatting)0, Array.Empty())); } else { outputLines.Enqueue(((JToken)val).ToString((Formatting)1, Array.Empty())); } } break; } } } }); } private static string GetHashString(string input) { using SHA256 sHA = SHA256.Create(); byte[] bytes = Encoding.UTF8.GetBytes(input); return Convert.ToBase64String(sHA.ComputeHash(bytes)); } } } namespace WubarrksEye.Adapters { internal static class BlackBoxAdapter { public static void OnPrefixPatched(object instance, MethodBase originalMethod) { try { if (!(originalMethod == null)) { string text = originalMethod.DeclaringType?.FullName ?? ""; string name = originalMethod.Name; WubarrkLogger.Info("[Eye][Prefix] " + text + "." + name); } } catch { } } public static void OnPostfixPatched(object instance, MethodBase originalMethod) { try { if (!(originalMethod == null)) { string text = originalMethod.DeclaringType?.FullName ?? ""; string name = originalMethod.Name; WubarrkLogger.Info("[Eye][Postfix] " + text + "." + name); } } catch { } } public static void LogPatchApplied(string patchId) { if (string.IsNullOrWhiteSpace(patchId)) { return; } try { WubarrkLogger.Info("[Eye][Codex] Patch applied: " + patchId); } catch { } } public static void LogPatchSkipped(string patchId, string reason) { if (string.IsNullOrWhiteSpace(patchId)) { return; } try { string text = (string.IsNullOrWhiteSpace(reason) ? "No details." : reason); WubarrkLogger.Warn("[Eye][Codex] Patch skipped: " + patchId + " — " + text); } catch { } } public static void LogPatchUnstable(string patchId, string note) { if (string.IsNullOrWhiteSpace(patchId)) { return; } try { string text = (string.IsNullOrWhiteSpace(note) ? "No details." : note); WubarrkLogger.Warn("[Eye][Codex] Patch unstable: " + patchId + " — " + text); } catch { } } public static void LogCodexReport(string path) { try { WubarrkLogger.Info("[Eye][Codex] CodexReport written: " + path); } catch { } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }