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 ValheimEffectListCompat v0.1.9
BepInEx\patchers\Ntxfloy-ValheimEffectListCompat\ValheimEffectListCompat.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx.Logging; using HarmonyLib; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyVersion("0.0.0.0")] namespace ValheimEffectListCompat; public static class Patcher { private static readonly ManualLogSource Log = Logger.CreateLogSource("Ntxfloy EffectList Compat"); private static bool resolverInstalled; public static IEnumerable<string> TargetDLLs => new string[2] { "assembly_valheim.dll", "OdinStorage.dll" }; public static void Patch(AssemblyDefinition assembly) { if (assembly != null) { if (((AssemblyNameReference)assembly.Name).Name == "assembly_valheim") { PatchValheim(assembly); } else if (((AssemblyNameReference)assembly.Name).Name == "OdinStorage") { PatchOdinStorage(assembly); } } } private static void PatchValheim(AssemblyDefinition assembly) { try { TypeDefinition type = assembly.MainModule.GetType("EffectList"); if (type == null) { Log.LogWarning((object)"EffectList type not found; no compatibility change applied."); } else { MethodDefinition val = ((IEnumerable<MethodDefinition>)type.Methods).SingleOrDefault((Func<MethodDefinition, bool>)IsNativeCreate); if (val == null) { Log.LogWarning((object)"Expected native EffectList.Create(..., ZDOID) overload not found; game API may have changed."); } else if (!((IEnumerable<MethodDefinition>)type.Methods).Any(IsLegacyCreate)) { AddEffectListLegacyForwarder(type, val); Log.LogInfo((object)"Added EffectList.Create(Vector3, Quaternion, Transform, Single, Int32) forwarder."); } else { Log.LogInfo((object)"Legacy EffectList.Create overload already exists; leaving unchanged."); } InstallHarmonyResolver(); } TypeDefinition type2 = assembly.MainModule.GetType("Character"); if (type2 == null) { Log.LogWarning((object)"Character type not found in assembly_valheim; skipping Character.Message patch."); return; } MethodDefinition val2 = ((IEnumerable<MethodDefinition>)type2.Methods).FirstOrDefault((Func<MethodDefinition, bool>)IsNativeCharacterMessage); if (val2 == null) { Log.LogWarning((object)"Expected 5-arg Character.Message not found; game API may have changed."); } else if (!((IEnumerable<MethodDefinition>)type2.Methods).Any(IsLegacyCharacterMessage)) { AddCharacterMessageForwarder(type2, val2, assembly.MainModule); Log.LogInfo((object)"Added Character.Message(MessageType, string, int, Sprite) forwarder -> 5-arg version."); } else { Log.LogInfo((object)"Legacy Character.Message(4 args) already exists; leaving unchanged."); } } catch (Exception ex) { Log.LogError((object)("assembly_valheim compatibility patch failed: " + ex)); } } private static void PatchOdinStorage(AssemblyDefinition assembly) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) try { int num = 0; foreach (TypeDefinition type in assembly.MainModule.GetTypes()) { Enumerator<MethodDefinition> enumerator2 = type.Methods.GetEnumerator(); try { while (enumerator2.MoveNext()) { MethodDefinition current = enumerator2.Current; if (!current.HasBody) { continue; } Collection<Instruction> instructions = current.Body.Instructions; ILProcessor iLProcessor = current.Body.GetILProcessor(); for (int i = 0; i < instructions.Count; i++) { Instruction val = instructions[i]; if (val.OpCode != OpCodes.Callvirt && val.OpCode != OpCodes.Call) { continue; } object operand = val.Operand; MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null); if (val2 != null && IsOdinStorage4ArgCharacterMessage(val2)) { MethodReference val3 = Build5ArgCharacterMessageRef(assembly.MainModule, val2); if (val3 != null) { Instruction val4 = iLProcessor.Create(OpCodes.Ldc_I4_0); iLProcessor.InsertBefore(val, val4); val.Operand = val3; num++; i++; } } } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } if (num > 0) { Log.LogInfo((object)$"OdinStorage.dll: rewrote {num} Character.Message(4-arg) callsites to 5-arg."); } else { Log.LogWarning((object)"OdinStorage.dll: no 4-arg Character.Message callsites found (already patched or API changed)."); } } catch (Exception ex) { Log.LogError((object)("OdinStorage.dll IL patch failed: " + ex)); } } private static bool IsOdinStorage4ArgCharacterMessage(MethodReference method) { if (((MemberReference)method).Name != "Message") { return false; } if (method.Parameters.Count != 4) { return false; } TypeReference declaringType = ((MemberReference)method).DeclaringType; string text = ((declaringType != null) ? ((MemberReference)declaringType).FullName : null) ?? ""; if (text != "Character" && !text.EndsWith(".Character")) { return false; } string fullName = ((MemberReference)((ParameterReference)method.Parameters[0]).ParameterType).FullName; string fullName2 = ((MemberReference)((ParameterReference)method.Parameters[1]).ParameterType).FullName; string fullName3 = ((MemberReference)((ParameterReference)method.Parameters[2]).ParameterType).FullName; string fullName4 = ((MemberReference)((ParameterReference)method.Parameters[3]).ParameterType).FullName; if ((fullName.Contains("MessageType") || fullName.Contains("MessageHud")) && fullName2 == "System.String" && fullName3 == "System.Int32") { return fullName4.Contains("Sprite"); } return false; } private static MethodReference Build5ArgCharacterMessageRef(ModuleDefinition module, MethodReference original4) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown try { TypeReference val = module.TypeSystem.Void; TypeReference boolean = module.TypeSystem.Boolean; MethodReference val2 = new MethodReference("Message", val, ((MemberReference)original4).DeclaringType) { HasThis = original4.HasThis, ExplicitThis = original4.ExplicitThis, CallingConvention = original4.CallingConvention }; Enumerator<ParameterDefinition> enumerator = original4.Parameters.GetEnumerator(); try { while (enumerator.MoveNext()) { ParameterDefinition current = enumerator.Current; val2.Parameters.Add(new ParameterDefinition(((ParameterReference)current).Name, current.Attributes, ((ParameterReference)current).ParameterType)); } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } val2.Parameters.Add(new ParameterDefinition("log", (ParameterAttributes)0, boolean)); return module.ImportReference(val2); } catch { return null; } } private static bool IsNativeCreate(MethodDefinition method) { if (((MemberReference)method).Name != "Create" || ((MethodReference)method).Parameters.Count != 6) { return false; } string[] array = new string[6] { "UnityEngine.Vector3", "UnityEngine.Quaternion", "UnityEngine.Transform", "System.Single", "System.Int32", "ZDOID" }; for (int i = 0; i < array.Length; i++) { if (((MemberReference)((ParameterReference)((MethodReference)method).Parameters[i]).ParameterType).FullName != array[i]) { return false; } } return true; } private static bool IsLegacyCreate(MethodDefinition method) { if (((MemberReference)method).Name != "Create" || ((MethodReference)method).Parameters.Count != 5) { return false; } string[] array = new string[5] { "UnityEngine.Vector3", "UnityEngine.Quaternion", "UnityEngine.Transform", "System.Single", "System.Int32" }; for (int i = 0; i < array.Length; i++) { if (((MemberReference)((ParameterReference)((MethodReference)method).Parameters[i]).ParameterType).FullName != array[i]) { return false; } } return true; } private static void AddEffectListLegacyForwarder(TypeDefinition type, MethodDefinition native) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_00f7: 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_011d: 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_0142: Unknown result type (might be due to invalid IL or missing references) MethodAttributes val = (MethodAttributes)134; if (native.IsStatic) { val = (MethodAttributes)(val | 0x10); } MethodDefinition val2 = new MethodDefinition("Create", val, ((MethodReference)native).ReturnType); for (int i = 0; i < 5; i++) { ParameterDefinition val3 = ((MethodReference)native).Parameters[i]; ((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)val3).Name, val3.Attributes, ((ParameterReference)val3).ParameterType)); } MethodBody body = val2.Body; body.InitLocals = true; body.MaxStackSize = 8; ILProcessor iLProcessor = body.GetILProcessor(); if (!native.IsStatic) { iLProcessor.Append(iLProcessor.Create(OpCodes.Ldarg_0)); } for (int j = 0; j < 5; j++) { iLProcessor.Append(iLProcessor.Create(OpCodes.Ldarg, ((MethodReference)val2).Parameters[j])); } TypeReference parameterType = ((ParameterReference)((MethodReference)native).Parameters[5]).ParameterType; VariableDefinition val4 = new VariableDefinition(parameterType); body.Variables.Add(val4); iLProcessor.Append(iLProcessor.Create(OpCodes.Ldloca, val4)); iLProcessor.Append(iLProcessor.Create(OpCodes.Initobj, parameterType)); iLProcessor.Append(iLProcessor.Create(OpCodes.Ldloc, val4)); iLProcessor.Append(iLProcessor.Create(OpCodes.Call, (MethodReference)(object)native)); iLProcessor.Append(iLProcessor.Create(OpCodes.Ret)); type.Methods.Add(val2); } private static bool IsNativeCharacterMessage(MethodDefinition method) { if (((MemberReference)method).Name != "Message" || ((MethodReference)method).Parameters.Count != 5) { return false; } string[] array = new string[5] { "MessageHud/MessageType", "System.String", "System.Int32", "UnityEngine.Sprite", "System.Boolean" }; for (int i = 0; i < array.Length; i++) { if (((MemberReference)((ParameterReference)((MethodReference)method).Parameters[i]).ParameterType).FullName != array[i]) { return false; } } return true; } private static bool IsLegacyCharacterMessage(MethodDefinition method) { if (((MemberReference)method).Name != "Message" || ((MethodReference)method).Parameters.Count != 4) { return false; } string[] array = new string[4] { "MessageHud/MessageType", "System.String", "System.Int32", "UnityEngine.Sprite" }; for (int i = 0; i < array.Length; i++) { if (((MemberReference)((ParameterReference)((MethodReference)method).Parameters[i]).ParameterType).FullName != array[i]) { return false; } } return true; } private static void AddCharacterMessageForwarder(TypeDefinition type, MethodDefinition native, ModuleDefinition module) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) //IL_001d: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) MethodAttributes val = (MethodAttributes)454; MethodDefinition val2 = new MethodDefinition("Message", val, module.TypeSystem.Void); for (int i = 0; i < 4; i++) { ParameterDefinition val3 = ((MethodReference)native).Parameters[i]; ((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)val3).Name, val3.Attributes, ((ParameterReference)val3).ParameterType)); } MethodBody body = val2.Body; body.InitLocals = false; body.MaxStackSize = 7; ILProcessor iLProcessor = body.GetILProcessor(); iLProcessor.Append(iLProcessor.Create(OpCodes.Ldarg_0)); for (int j = 0; j < 4; j++) { iLProcessor.Append(iLProcessor.Create(OpCodes.Ldarg, ((MethodReference)val2).Parameters[j])); } iLProcessor.Append(iLProcessor.Create(OpCodes.Ldc_I4_0)); iLProcessor.Append(iLProcessor.Create(OpCodes.Callvirt, (MethodReference)(object)native)); iLProcessor.Append(iLProcessor.Create(OpCodes.Ret)); type.Methods.Add(val2); } private static void InstallHarmonyResolver() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown if (!resolverInstalled) { MethodInfo method = typeof(AccessTools).GetMethod("DeclaredMethod", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(Type), typeof(string), typeof(Type[]), typeof(Type[]) }, null); MethodInfo method2 = typeof(Patcher).GetMethod("ResolveEffectListPatchTarget", BindingFlags.Static | BindingFlags.NonPublic); if (method == null || method2 == null) { Log.LogWarning((object)"Harmony resolver hook could not be installed; by-name patches may remain ambiguous."); return; } new Harmony("Ntxfloy.ValheimEffectListCompat").Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); resolverInstalled = true; Log.LogInfo((object)"Harmony by-name lookup selects the original EffectList.Create overload by metadata order."); } } private static bool ResolveEffectListPatchTarget(Type type, string name, Type[] parameters, Type[] generics, ref MethodInfo __result) { if (type == null || type.Name != "EffectList" || type.Assembly.GetName().Name != "assembly_valheim" || name != "Create" || parameters != null) { return true; } MethodInfo[] array = (from m in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "Create" orderby m.MetadataToken select m).ToArray(); if (array.Length != 2 || array[0].MetadataToken >= array[1].MetadataToken) { return true; } __result = array[0]; return false; } }
BepInEx\plugins\Ntxfloy-ValheimSceneCompat\ValheimSceneCompat.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] namespace ValheimSceneCompat; [BepInPlugin("ntxfloy.valheimscenecompat", "Valheim Scene Compatibility", "0.1.7")] public class Plugin : BaseUnityPlugin { private class ErrorThrottle { private class ErrorEntry { public float LastLogTime; public int SuppressedCount; } private const int MaxTrackedSignatures = 200; private readonly string _tag; private readonly Dictionary<string, ErrorEntry> _entries = new Dictionary<string, ErrorEntry>(32); private ErrorEntry _overflowEntry; public ErrorThrottle(string tag) { _tag = tag; } public void Log(string context, Exception ex) { string signature = GetSignature(context, ex); float unscaledTime = Time.unscaledTime; if (!_entries.TryGetValue(signature, out var value)) { if (_entries.Count < 200) { value = new ErrorEntry { LastLogTime = unscaledTime, SuppressedCount = 0 }; _entries[signature] = value; } else { if (_overflowEntry == null) { _overflowEntry = new ErrorEntry { LastLogTime = unscaledTime, SuppressedCount = 0 }; } value = _overflowEntry; } string text = ((ex != null) ? (ex.GetType().Name + ": " + ex.Message + "\n" + ex.StackTrace) : context); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[" + _tag + "] [First occurrence] " + context + ": " + text)); } return; } value.SuppressedCount++; if (unscaledTime - value.LastLogTime >= 10f) { value.LastLogTime = unscaledTime; string text2 = ((ex != null) ? (ex.GetType().Name + ": " + ex.Message + "\n" + ex.StackTrace) : context); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)$"[{_tag}] [{value.SuppressedCount} events throttled] {context}: {text2}"); } value.SuppressedCount = 0; } } private static string GetSignature(string context, Exception ex) { if (ex == null) { return context ?? "unknown"; } string stackTrace = ex.StackTrace; string text = "no_stack"; if (!string.IsNullOrEmpty(stackTrace)) { int num = stackTrace.IndexOfAny(new char[2] { '\r', '\n' }); text = ((num > 0) ? stackTrace.Substring(0, num).Trim() : stackTrace.Trim()); } return ex.GetType().Name + " @ " + text + " (" + context + ")"; } } internal static ManualLogSource Log; private static readonly List<ZDO> s_deadKeys = new List<ZDO>(64); private static readonly ErrorThrottle s_removeObjectsThrottle = new ErrorThrottle("SceneCompat:RemoveObjects"); private static readonly ErrorThrottle s_createDestroyThrottle = new ErrorThrottle("SceneCompat:CreateDestroyObjects"); private static readonly ErrorThrottle s_doubleZNetViewThrottle = new ErrorThrottle("DoubleZNetview Guard"); public static ConfigEntry<bool> EnableSafeRemoveObjects; public static ConfigEntry<bool> EnableCreateDestroyFinalizer; public static ConfigEntry<bool> PreventDoubleZNetViewGhostZDO; private void Awake() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_0179: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; EnableSafeRemoveObjects = ((BaseUnityPlugin)this).Config.Bind<bool>("ZNetScene", "EnableSafeRemoveObjects", true, "Enables dictionary sanitization and guaranteed removal in ZNetScene.RemoveObjects, preventing Unity 6 NRE cascades."); EnableCreateDestroyFinalizer = ((BaseUnityPlugin)this).Config.Bind<bool>("ZNetScene", "EnableCreateDestroyFinalizer", true, "Installs a safety Finalizer on ZNetScene.CreateDestroyObjects to catch and suppress unhandled exceptions, preventing the main loop from aborting."); PreventDoubleZNetViewGhostZDO = ((BaseUnityPlugin)this).Config.Bind<bool>("ZNetScene", "PreventDoubleZNetViewGhostZDO", false, "Experimental: Destroys duplicate ZNetViews on instantiated prefabs instead of creating unmanaged ghost ZDOs in ZDOMan. Default is false."); Harmony val = new Harmony("ntxfloy.valheimscenecompat"); if (EnableSafeRemoveObjects.Value) { Type typeFromHandle = typeof(ZNetScene); MethodInfo method = typeFromHandle.GetMethod("RemoveObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(List<ZDO>), typeof(List<ZDO>) }, null); FieldInfo field = typeFromHandle.GetField("m_instances", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeFromHandle.GetField("m_tempRemoved", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null && field != null && field2 != null && field.FieldType == typeof(Dictionary<ZDO, ZNetView>) && field2.FieldType == typeof(List<ZNetView>)) { MethodInfo method2 = typeof(Plugin).GetMethod("RemoveObjectsPrefix", BindingFlags.Static | BindingFlags.Public); MethodInfo method3 = typeof(Plugin).GetMethod("RemoveObjectsFinalizer", BindingFlags.Static | BindingFlags.Public); val.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null); Log.LogInfo((object)"Hooked ZNetScene.RemoveObjects with safe dictionary sanitization, guaranteed removal, and finalizer."); } else { Log.LogWarning((object)"ZNetScene.RemoveObjects signature or fields changed; safe RemoveObjects patch skipped safely."); } } if (EnableCreateDestroyFinalizer.Value) { MethodInfo method4 = typeof(ZNetScene).GetMethod("CreateDestroyObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method4 != null) { MethodInfo method5 = typeof(Plugin).GetMethod("CreateDestroyObjectsFinalizer", BindingFlags.Static | BindingFlags.Public); val.Patch((MethodBase)method4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method5), (HarmonyMethod)null); Log.LogInfo((object)"Installed safety Finalizer on ZNetScene.CreateDestroyObjects."); } } if (PreventDoubleZNetViewGhostZDO.Value) { MethodInfo method6 = typeof(ZNetView).GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method6 != null) { MethodInfo method7 = typeof(Plugin).GetMethod("ZNetViewAwakePrefix", BindingFlags.Static | BindingFlags.Public); val.Patch((MethodBase)method6, new HarmonyMethod(method7), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Installed DoubleZNetview duplicate suppression on ZNetView.Awake."); } } } public static bool RemoveObjectsPrefix(ZNetScene __instance, Dictionary<ZDO, ZNetView> ___m_instances, List<ZNetView> ___m_tempRemoved, List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects) { if (___m_instances == null || ___m_tempRemoved == null) { return true; } byte b = (byte)(Time.frameCount & 0xFF); if (currentNearObjects != null) { for (int i = 0; i < currentNearObjects.Count; i++) { ZDO val = currentNearObjects[i]; if (val != null) { val.TempRemoveEarmark = b; } } } if (currentDistantObjects != null) { for (int j = 0; j < currentDistantObjects.Count; j++) { ZDO val2 = currentDistantObjects[j]; if (val2 != null) { val2.TempRemoveEarmark = b; } } } ___m_tempRemoved.Clear(); s_deadKeys.Clear(); foreach (KeyValuePair<ZDO, ZNetView> ___m_instance in ___m_instances) { ZDO key = ___m_instance.Key; ZNetView value = ___m_instance.Value; if (key == null || value == null || (Object)(object)value == (Object)null) { s_deadKeys.Add(key); continue; } ZDO val3 = null; try { val3 = value.GetZDO(); } catch (Exception ex) { s_removeObjectsThrottle.Log("Error retrieving ZDO from ZNetView during sanitization", ex); } if (val3 == null || val3 != key) { s_deadKeys.Add(key); } else if (val3.TempRemoveEarmark != b) { ___m_tempRemoved.Add(value); } } for (int k = 0; k < s_deadKeys.Count; k++) { ZDO val4 = s_deadKeys[k]; if (val4 != null) { ___m_instances.Remove(val4); } } s_deadKeys.Clear(); for (int l = 0; l < ___m_tempRemoved.Count; l++) { ZNetView val5 = ___m_tempRemoved[l]; if (val5 == null) { continue; } ZDO val6 = null; try { val6 = val5.GetZDO(); val5.ResetZDO(); if (val6 != null) { try { if (!val6.Persistent && val6.IsOwner()) { ZDOMan instance = ZDOMan.instance; if (instance != null) { instance.DestroyZDO(val6); } } } catch (Exception ex2) { s_removeObjectsThrottle.Log("Error checking persistence or destroying non-persistent ZDO in RemoveObjects", ex2); } } if ((Object)(object)val5 != (Object)null) { GameObject val7 = null; try { val7 = ((Component)val5).gameObject; } catch (Exception ex3) { s_removeObjectsThrottle.Log("Component.gameObject threw on destroyed entity in RemoveObjects", ex3); } if ((Object)(object)val7 != (Object)null) { Object.Destroy((Object)(object)val7); } } } catch (Exception ex4) { s_removeObjectsThrottle.Log("Error resetting or destroying ZNetView in RemoveObjects", ex4); } finally { if (val6 != null) { ___m_instances.Remove(val6); } } } return false; } public static Exception RemoveObjectsFinalizer(Exception __exception) { if (__exception != null) { s_removeObjectsThrottle.Log("Unhandled exception in RemoveObjects", __exception); return null; } return null; } public static Exception CreateDestroyObjectsFinalizer(Exception __exception) { if (__exception != null) { s_createDestroyThrottle.Log("External exception in CreateDestroyObjects", __exception); return null; } return null; } public static bool ZNetViewAwakePrefix(ZNetView __instance) { if (!PreventDoubleZNetViewGhostZDO.Value) { return true; } if (ZNetView.m_useInitZDO && ZNetView.m_initZDO == null) { try { string text = (((Object)(object)((__instance != null) ? ((Component)__instance).gameObject : null) != (Object)null) ? ((Object)((Component)__instance).gameObject).name : "unknown"); s_doubleZNetViewThrottle.Log("Prevented ghost ZDO creation on duplicate ZNetView on " + text + ". Destroying duplicate component.", null); if ((Object)(object)__instance != (Object)null) { ((Behaviour)__instance).enabled = false; Object.Destroy((Object)(object)__instance); } } catch (Exception ex) { s_doubleZNetViewThrottle.Log("Error in ZNetViewAwakePrefix duplicate suppression", ex); } return false; } return true; } }