Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Monstrum Location Manager Fix v1.0.1
MonstrumLocationManagerFix.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("MonstrumLocationManagerFix")] [assembly: AssemblyProduct("MonstrumLocationManagerFix")] [assembly: AssemblyCompany("sighsorry")] [assembly: AssemblyMetadata("Author", "sighsorry")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MonstrumLocationManagerFix { [BepInPlugin("sighsorry.MonstrumLocationManagerFix", "MonstrumLocationManagerFix", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class MonstrumLocationManagerFixPlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <FindTargetMethods>d__32 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private HashSet<string> <seenMethods>5__1; private Assembly[] <>s__2; private int <>s__3; private Assembly <assembly>5__4; private Type <locationType>5__5; private MethodInfo[] <methods>5__6; private MethodInfo[] <>s__7; private int <>s__8; private MethodInfo <method>5__9; private string <methodKey>5__10; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FindTargetMethods>d__32(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <seenMethods>5__1 = null; <>s__2 = null; <assembly>5__4 = null; <locationType>5__5 = null; <methods>5__6 = null; <>s__7 = null; <method>5__9 = null; <methodKey>5__10 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_01ed; } <>1__state = -1; <seenMethods>5__1 = new HashSet<string>(StringComparer.Ordinal); <>s__2 = AppDomain.CurrentDomain.GetAssemblies(); <>s__3 = 0; goto IL_0248; IL_0248: if (<>s__3 < <>s__2.Length) { <assembly>5__4 = <>s__2[<>s__3]; if (IsTargetPluginAssembly(<assembly>5__4)) { <locationType>5__5 = <assembly>5__4.GetType("LocationManager.Location", throwOnError: false); if ((object)<locationType>5__5 == null) { ManualLogSource? logSource = LogSource; if (logSource != null) { logSource.LogWarning((object)("Found target plugin assembly " + <assembly>5__4.GetName().Name + ", but type LocationManager.Location was missing.")); } } else { <methods>5__6 = (from method in <locationType>5__5.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where string.Equals(method.Name, "AddLocationToZoneSystem", StringComparison.Ordinal) select method).ToArray(); if (<methods>5__6.Length != 0) { <>s__7 = <methods>5__6; <>s__8 = 0; goto IL_020a; } ManualLogSource? logSource2 = LogSource; if (logSource2 != null) { logSource2.LogWarning((object)("Found target type LocationManager.Location in " + <assembly>5__4.GetName().Name + ", but method AddLocationToZoneSystem was missing.")); } } } goto IL_023a; } <>s__2 = null; return false; IL_020a: if (<>s__8 < <>s__7.Length) { <method>5__9 = <>s__7[<>s__8]; <methodKey>5__10 = $"{<method>5__9.Module.ModuleVersionId:N}:{<method>5__9.MetadataToken}"; if (<seenMethods>5__1.Add(<methodKey>5__10)) { <>2__current = <method>5__9; <>1__state = 1; return true; } goto IL_01ed; } <>s__7 = null; <locationType>5__5 = null; <methods>5__6 = null; <assembly>5__4 = null; goto IL_023a; IL_023a: <>s__3++; goto IL_0248; IL_01ed: <methodKey>5__10 = null; <method>5__9 = null; <>s__8++; goto IL_020a; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <FindTargetMethods>d__32(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <ReplaceDestroyWithDestroyImmediate>d__38 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private MethodBase original; public MethodBase <>3__original; private int <replacements>5__1; private bool <hasDestroyImmediateCall>5__2; private string <declaringAssemblyName>5__3; private IEnumerator<CodeInstruction> <>s__4; private CodeInstruction <instruction>5__5; private IEnumerator<CodeInstruction> <>s__6; private CodeInstruction <instruction>5__7; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ReplaceDestroyWithDestroyImmediate>d__38(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { switch (<>1__state) { case -3: case 1: try { } finally { <>m__Finally1(); } break; case -4: case 2: try { } finally { <>m__Finally2(); } break; } <declaringAssemblyName>5__3 = null; <>s__4 = null; <instruction>5__5 = null; <>s__6 = null; <instruction>5__7 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((object)DestroyMethod == null || (object)DestroyImmediateMethod == null) { <>s__4 = instructions.GetEnumerator(); <>1__state = -3; goto IL_00a2; } <replacements>5__1 = 0; <hasDestroyImmediateCall>5__2 = false; <>s__6 = instructions.GetEnumerator(); <>1__state = -4; break; case 1: <>1__state = -3; <instruction>5__5 = null; goto IL_00a2; case 2: { <>1__state = -4; <instruction>5__7 = null; break; } IL_00a2: if (<>s__4.MoveNext()) { <instruction>5__5 = <>s__4.Current; <>2__current = <instruction>5__5; <>1__state = 1; return true; } <>m__Finally1(); <>s__4 = null; return false; } if (<>s__6.MoveNext()) { <instruction>5__7 = <>s__6.Current; if (CodeInstructionExtensions.Calls(<instruction>5__7, DestroyImmediateMethod)) { <hasDestroyImmediateCall>5__2 = true; } if (CodeInstructionExtensions.Calls(<instruction>5__7, DestroyMethod)) { <instruction>5__7.operand = DestroyImmediateMethod; <replacements>5__1++; <hasDestroyImmediateCall>5__2 = true; } <>2__current = <instruction>5__7; <>1__state = 2; return true; } <>m__Finally2(); <>s__6 = null; <declaringAssemblyName>5__3 = original.DeclaringType?.Assembly.GetName().Name ?? "unknown"; if (<replacements>5__1 > 0) { ManualLogSource? logSource = LogSource; if (logSource != null) { logSource.LogInfo((object)string.Format("Patched {0}.{1}.{2} and replaced {3} Destroy call(s).", <declaringAssemblyName>5__3, "LocationManager.Location", original.Name, <replacements>5__1)); } return false; } if (<hasDestroyImmediateCall>5__2) { ManualLogSource? logSource2 = LogSource; if (logSource2 != null) { logSource2.LogInfo((object)("Verified " + <declaringAssemblyName>5__3 + ".LocationManager.Location." + original.Name + " is already using DestroyImmediate.")); } return false; } ManualLogSource? logSource3 = LogSource; if (logSource3 != null) { logSource3.LogWarning((object)("No matching Destroy(Object) call was found in " + <declaringAssemblyName>5__3 + ".LocationManager.Location." + original.Name + ".")); } return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__4 != null) { <>s__4.Dispose(); } } private void <>m__Finally2() { <>1__state = -1; if (<>s__6 != null) { <>s__6.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <ReplaceDestroyWithDestroyImmediate>d__38 <ReplaceDestroyWithDestroyImmediate>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <ReplaceDestroyWithDestroyImmediate>d__ = this; } else { <ReplaceDestroyWithDestroyImmediate>d__ = new <ReplaceDestroyWithDestroyImmediate>d__38(0); } <ReplaceDestroyWithDestroyImmediate>d__.instructions = <>3__instructions; <ReplaceDestroyWithDestroyImmediate>d__.original = <>3__original; return <ReplaceDestroyWithDestroyImmediate>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } internal const string PluginGuid = "sighsorry.MonstrumLocationManagerFix"; internal const string PluginName = "MonstrumLocationManagerFix"; internal const string PluginVersion = "1.0.1"; private const string ExpandWorldDataGuid = "expand_world_data"; private const string ExpandWorldDataDataManagerTypeFullName = "ExpandWorldData.DataManager"; private const string ExpandWorldDataCleanGhostInitMethodName = "CleanGhostInit"; private const string TargetTypeFullName = "LocationManager.Location"; private const string TargetMethodName = "AddLocationToZoneSystem"; private const string ZdoTypeFullName = "ZDO"; private const string ZNetSceneTypeFullName = "ZNetScene"; private const string ZNetViewTypeFullName = "ZNetView"; private static readonly HashSet<string> TargetPluginGuids = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Therzie.Monstrum", "Therzie.MonstrumDeepNorth" }; private static readonly MethodInfo? DestroyMethod = AccessTools.Method(typeof(Object), "Destroy", new Type[1] { typeof(Object) }, (Type[])null); private static readonly MethodInfo? DestroyImmediateMethod = AccessTools.Method(typeof(Object), "DestroyImmediate", new Type[1] { typeof(Object) }, (Type[])null); private static readonly Type? ZdoType = AccessTools.TypeByName("ZDO"); private static readonly Type? ZNetSceneType = AccessTools.TypeByName("ZNetScene"); private static readonly Type? ZNetViewType = AccessTools.TypeByName("ZNetView"); private static readonly MethodInfo? ZdoCreatedSetter = (((object)ZdoType == null) ? null : AccessTools.PropertySetter(ZdoType, "Created")); private static readonly MethodInfo? ZNetSceneInstanceGetter = (((object)ZNetSceneType == null) ? null : AccessTools.PropertyGetter(ZNetSceneType, "instance")); private static readonly FieldInfo? ZNetSceneInstancesField = (((object)ZNetSceneType == null) ? null : AccessTools.Field(ZNetSceneType, "m_instances")); private static readonly MethodInfo? ZNetViewGetZdoMethod = (((object)ZNetViewType == null) ? null : AccessTools.Method(ZNetViewType, "GetZDO", (Type[])null, (Type[])null)); private static readonly FieldInfo? ZNetViewGhostField = (((object)ZNetViewType == null) ? null : AccessTools.Field(ZNetViewType, "m_ghost")); private static readonly FieldInfo? ZNetViewGhostInitField = (((object)ZNetViewType == null) ? null : AccessTools.Field(ZNetViewType, "m_ghostInit")); private static ManualLogSource? LogSource; private static bool loggedExpandWorldDataMissingScene; private static bool loggedExpandWorldDataMissingZdo; private static bool loggedExpandWorldDataReflectionFailure; private Harmony? harmony; private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown LogSource = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("sighsorry.MonstrumLocationManagerFix"); try { int num = 0; num += ApplyLocationManagerFixes(); if (num + ApplyExpandWorldDataCompatibilityFix() == 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"No compatible target assemblies were found. Nothing to patch."); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to apply runtime patch: {arg}"); } } private void OnDestroy() { Harmony? obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private int ApplyLocationManagerFixes() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown if ((object)DestroyMethod == null || (object)DestroyImmediateMethod == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not resolve UnityEngine.Object destroy methods for LocationManager patching."); return 0; } MethodBase[] array = FindTargetMethods().ToArray(); if (array.Length == 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"No loaded Therzie Monstrum assemblies were found for the LocationManager fix."); return 0; } MethodBase[] array2 = array; foreach (MethodBase methodBase in array2) { harmony.Patch(methodBase, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(MonstrumLocationManagerFixPlugin), "ReplaceDestroyWithDestroyImmediate", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Applied runtime patch to {array.Length} LocationManager method(s)."); return array.Length; } private int ApplyExpandWorldDataCompatibilityFix() { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown Type type = AccessTools.TypeByName("ExpandWorldData.DataManager"); if ((object)type == null) { return 0; } if ((object)ZNetViewType == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Expand World Data was detected, but the Valheim ZNetView type could not be resolved."); return 0; } if ((object)ZNetViewGhostField == null || (object)ZNetViewGhostInitField == null || (object)ZNetViewGetZdoMethod == null || (object)ZNetSceneInstanceGetter == null || (object)ZNetSceneInstancesField == null || (object)ZdoCreatedSetter == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Expand World Data was detected, but the required Valheim ghost cleanup members could not be resolved."); return 0; } MethodInfo methodInfo = AccessTools.Method(type, "CleanGhostInit", new Type[1] { ZNetViewType }, (Type[])null); if ((object)methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Expand World Data was detected, but DataManager.CleanGhostInit(ZNetView) could not be found."); return 0; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(MonstrumLocationManagerFixPlugin), "ExpandWorldDataCleanGhostInitPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Applied Expand World Data compatibility patch to DataManager.CleanGhostInit(ZNetView)."); return 1; } [IteratorStateMachine(typeof(<FindTargetMethods>d__32))] private static IEnumerable<MethodBase> FindTargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FindTargetMethods>d__32(-2); } private static bool IsTargetPluginAssembly(Assembly assembly) { try { foreach (Type item in SafeGetTypes(assembly)) { object[] customAttributes = item.GetCustomAttributes(typeof(BepInPlugin), inherit: false); foreach (BepInPlugin item2 in customAttributes.OfType<BepInPlugin>()) { if (TargetPluginGuids.Contains(item2.GUID)) { return true; } } } } catch (Exception ex) { ManualLogSource? logSource = LogSource; if (logSource != null) { logSource.LogDebug((object)("Skipping assembly " + assembly.GetName().Name + " during target scan: " + ex.Message)); } } return false; } private static IEnumerable<Type> SafeGetTypes(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type type) => (object)type != null); } } public static bool ExpandWorldDataCleanGhostInitPrefix(object? __0) { if (!IsGhostInitActive() || __0 == null) { return false; } try { if ((object)ZNetViewGhostField == null || (object)ZNetViewGetZdoMethod == null || (object)ZNetSceneInstanceGetter == null || (object)ZNetSceneInstancesField == null || (object)ZdoCreatedSetter == null) { LogExpandWorldDataCompatibilityWarning(ref loggedExpandWorldDataReflectionFailure, "Skipped Expand World Data ghost cleanup because required Valheim fields could not be resolved."); return false; } ZNetViewGhostField.SetValue(__0, true); object obj = ZNetViewGetZdoMethod.Invoke(__0, Array.Empty<object>()); if (obj == null) { LogExpandWorldDataCompatibilityWarning(ref loggedExpandWorldDataMissingZdo, "Skipped Expand World Data ghost cleanup because the spawned ZNetView had no ZDO."); return false; } object obj2 = ZNetSceneInstanceGetter.Invoke(null, Array.Empty<object>()); if (obj2 == null || !(ZNetSceneInstancesField.GetValue(obj2) is IDictionary dictionary)) { LogExpandWorldDataCompatibilityWarning(ref loggedExpandWorldDataMissingScene, "Skipped Expand World Data ghost cleanup because ZNetScene instance tracking was unavailable."); return false; } ZdoCreatedSetter.Invoke(obj, new object[1] { false }); dictionary.Remove(obj); } catch (Exception ex) { LogExpandWorldDataCompatibilityWarning(ref loggedExpandWorldDataReflectionFailure, "Expand World Data compatibility patch failed while cleaning ghost init: " + ex.Message); } return false; } private static bool IsGhostInitActive() { object obj = ZNetViewGhostInitField?.GetValue(null); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static void LogExpandWorldDataCompatibilityWarning(ref bool alreadyLogged, string message) { if (!alreadyLogged) { alreadyLogged = true; ManualLogSource? logSource = LogSource; if (logSource != null) { logSource.LogWarning((object)message); } } } [IteratorStateMachine(typeof(<ReplaceDestroyWithDestroyImmediate>d__38))] public static IEnumerable<CodeInstruction> ReplaceDestroyWithDestroyImmediate(IEnumerable<CodeInstruction> instructions, MethodBase original) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ReplaceDestroyWithDestroyImmediate>d__38(-2) { <>3__instructions = instructions, <>3__original = original }; } } }