Decompiled source of NullReferenceFix v1.0.5

NullReferenceFix.dll

Decompiled a day ago
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<ZDO, ZNetView> dictionary))
				{
					return null;
				}
				List<ZDO> list = new List<ZDO>();
				foreach (KeyValuePair<ZDO, ZNetView> 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<Container> hashSet))
				{
					return 0;
				}
				List<Container> list = new List<Container>();
				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;
			}
		}
	}
}