using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; 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("NullReferenceFix")] [assembly: AssemblyDescription("Fixes a vanilla Valheim NullReferenceException loop in ZNetScene.RemoveObjects.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("KorCaptain")] [assembly: AssemblyProduct("NullReferenceFix")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("B3C1F0F1-6E8C-4B7A-9B2E-1E7F5C9A2D41")] [assembly: AssemblyFileVersion("1.0.5")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.5.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } } namespace NullReferenceFix { [BepInPlugin("KorCaptain.NullReferenceFix", "NullReferenceFix", "1.0.5")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class NullReferenceFixPlugin : BaseUnityPlugin { internal const string ModVersion = "1.0.5"; internal const string ModName = "NullReferenceFix"; internal const string Author = "KorCaptain"; private const string ModGUID = "KorCaptain.NullReferenceFix"; private readonly Harmony _harmony = new Harmony("KorCaptain.NullReferenceFix"); public static ManualLogSource NullReferenceFixLogger; public void Awake() { NullReferenceFixLogger = ((BaseUnityPlugin)this).Logger; _harmony.PatchAll(Assembly.GetExecutingAssembly()); NullReferenceFixLogger.LogInfo((object)"NullReferenceFix v1.0.5 loaded."); } } } namespace NullReferenceFix.Patches { [HarmonyPatch(typeof(ZNetScene), "RemoveObjects")] public static class ZNetScene_RemoveObjects_NullGuard_Patch { private static readonly FieldInfo? InstancesField = typeof(ZNetScene).GetField("m_instances", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static Exception? Finalizer(ZNetScene __instance, Exception __exception) { if (!(__exception is NullReferenceException)) { return __exception; } try { if (!(InstancesField?.GetValue(__instance) is Dictionary dictionary)) { return null; } List list = new List(); foreach (KeyValuePair item in dictionary) { if ((Object)(object)item.Value == (Object)null) { list.Add(item.Key); } } foreach (ZDO item2 in list) { dictionary.Remove(item2); } if (list.Count > 0) { NullReferenceFixPlugin.NullReferenceFixLogger.LogWarning((object)string.Format("[NullFix] Cleared {0} stale ZNetView entr{1} that caused a ZNetScene.RemoveObjects NullReferenceException.", list.Count, (list.Count == 1) ? "y" : "ies")); } } catch (Exception arg) { NullReferenceFixPlugin.NullReferenceFixLogger.LogError((object)$"Failed to clean up stale ZNetView entries: {arg}"); } return null; } } [HarmonyPatch] public static class AzuCraftyBoxes_HaveRequirements_NullGuard_Patch { private const string AzuCraftyBoxesPluginGuid = "Azumatt.AzuCraftyBoxes"; private static readonly FieldInfo? ContainersField = ResolveContainersField(); private static bool Prepare() { return TargetMethod() != null; } private static MethodBase? TargetMethod() { Type type = ResolveAzuCraftyBoxesType("AzuCraftyBoxes.Patches.PlayerHaveRequirementsPatchRBoolInt"); return (type == null) ? null : AccessTools.DeclaredMethod(type, "Postfix", (Type[])null, (Type[])null); } private static FieldInfo? ResolveContainersField() { Type type = ResolveAzuCraftyBoxesType("AzuCraftyBoxes.Util.Functions.Boxes"); return (type == null) ? null : AccessTools.Field(type, "Containers"); } private static Type? ResolveAzuCraftyBoxesType(string typeName) { if (!Chainloader.PluginInfos.TryGetValue("Azumatt.AzuCraftyBoxes", out var value)) { return null; } return ((object)value.Instance)?.GetType().Assembly.GetType(typeName); } private static Exception? Finalizer(Exception __exception) { if (!(__exception is NullReferenceException)) { return __exception; } int num = RemoveDestroyedContainers(); NullReferenceFixPlugin.NullReferenceFixLogger.LogWarning((object)((num > 0) ? string.Format("[NullFix] Cleared {0} stale (destroyed) container entr{1} that caused an AzuCraftyBoxes NullReferenceException during a recipe check.", num, (num == 1) ? "y" : "ies") : "[NullFix] Swallowed a NullReferenceException from AzuCraftyBoxes' recipe container check.")); return null; } private static int RemoveDestroyedContainers() { try { if (!(ContainersField?.GetValue(null) is HashSet hashSet)) { return 0; } List list = new List(); foreach (Container item in hashSet) { if ((Object)(object)item == (Object)null) { list.Add(item); } } foreach (Container item2 in list) { hashSet.Remove(item2); } return list.Count; } catch (Exception arg) { NullReferenceFixPlugin.NullReferenceFixLogger.LogError((object)$"Failed to clean up stale AzuCraftyBoxes container entries: {arg}"); return 0; } } } }