Decompiled source of AddChamberTriggerToEveryGun v1.0.1

Niko666.AddChamberTriggerToEveryGun.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using Valve.Newtonsoft.Json;
using Valve.Newtonsoft.Json.Converters;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Niko666")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Add chamber triggers to every gun so you can manually insert a round into the chamber.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("Niko666.AddChamberTriggerToEveryGun")]
[assembly: AssemblyTitle("AddChamberTriggerToEveryGun")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.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;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace Niko666
{
	internal static class ChamberTriggerPatch
	{
		[HarmonyPatch(typeof(FVRFireArmChamber), "Awake")]
		[HarmonyPostfix]
		private static void Awake_Postfix(FVRFireArmChamber __instance)
		{
			try
			{
				ChamberTrigger.Process(__instance);
			}
			catch (Exception ex)
			{
				ChamberTrigger.ReportProblem("Giving a chamber its trigger failed", ex);
			}
		}
	}
	internal static class ClosedBoltAccessPatch
	{
		[HarmonyPatch(typeof(ClosedBolt), "UpdateBolt")]
		[HarmonyPostfix]
		private static void UpdateBolt_Postfix(ClosedBolt __instance)
		{
			try
			{
				ChamberTrigger.PublishAccessibility(__instance);
			}
			catch (Exception ex)
			{
				ChamberTrigger.ReportProblem("Keeping a closed bolt's chamber state in step failed", ex);
			}
		}
	}
	internal static class AttachableClosedBoltAccessPatch
	{
		[HarmonyPatch(typeof(AttachableClosedBolt), "UpdateBolt")]
		[HarmonyPostfix]
		private static void UpdateBolt_Postfix(AttachableClosedBolt __instance)
		{
			try
			{
				ChamberTrigger.PublishAccessibility(__instance);
			}
			catch (Exception ex)
			{
				ChamberTrigger.ReportProblem("Keeping an attached closed bolt's chamber state in step failed", ex);
			}
		}
	}
	internal static class HeldRoundPassPatch
	{
		[HarmonyPatch(typeof(FVRFireArmRound), "UpdateInteraction", new Type[] { typeof(FVRViveHand) })]
		[HarmonyPostfix]
		private static void UpdateInteraction_Postfix(FVRFireArmRound __instance)
		{
			try
			{
				ChamberTrigger.WatchHeldRound(__instance);
			}
			catch (Exception ex)
			{
				ChamberTrigger.ReportProblem("Watching a held round failed", ex);
			}
		}
	}
	internal static class OpenBoltLockPatch
	{
		[HarmonyPatch(typeof(OpenBoltReceiverBolt), "UpdateBolt")]
		[HarmonyPrefix]
		private static void UpdateBolt_Prefix(OpenBoltReceiverBolt __instance)
		{
			try
			{
				ChamberTrigger.RelaxBoltLockRequirement(__instance);
			}
			catch (Exception ex)
			{
				ChamberTrigger.ReportProblem("Relaxing a bolt lock requirement failed", ex);
			}
		}
	}
	public sealed class ChamberTriggerMarker : MonoBehaviour
	{
		public Collider Driver;

		public bool Managed;

		public bool Adopted;

		public bool HasVanillaCollider;

		public Collider VanillaCollider;

		public bool OriginalsSaved;

		public Vector3 OriginalCenter;

		public Vector3 OriginalBoxSize;

		public float OriginalRadius;

		public float OriginalHeight;

		public int OriginalCapsuleDirection;

		public bool OriginalIsTrigger;

		public bool OriginalEnabled;

		public bool OriginalManuallyChamberable;

		public string OriginalTag;

		public bool RoundTypeSaved;

		public FireArmRoundType OriginalRoundType;

		public GameObject Visual;

		public int VisualPrimitive = -1;
	}
	public sealed class HeldRoundPassThrough : MonoBehaviour
	{
		private FVRFireArmRound _round;

		private Collider[] _roundColliders;

		private Collider[] _gunColliders;

		private GameObject _gun;

		private void Awake()
		{
			_round = ((Component)this).GetComponent<FVRFireArmRound>();
		}

		private void Update()
		{
			if ((Object)(object)_round == (Object)null || !((FVRInteractiveObject)_round).IsHeld)
			{
				Release();
				Object.Destroy((Object)(object)this);
				return;
			}
			if (!ChamberTrigger.FindGunToPassThrough(_round, AddChamberTriggerToEveryGun.Cfg.HeldRoundPassRange, out var gun))
			{
				Release();
				return;
			}
			if ((Object)(object)_gun != (Object)(object)((Component)gun).gameObject)
			{
				Release();
				_gun = ((Component)gun).gameObject;
				if (_roundColliders == null)
				{
					_roundColliders = CollectPhysColliders(((Component)_round).gameObject);
				}
				_gunColliders = CollectPhysColliders(((Component)gun).gameObject);
				if (AddChamberTriggerToEveryGun.Cfg.Verbose)
				{
					ChamberTrigger.LogPassThrough(gun, _roundColliders.Length, _gunColliders.Length);
				}
			}
			Ignore(ignore: true);
		}

		private void Release()
		{
			if ((Object)(object)_gun != (Object)null)
			{
				Ignore(ignore: false);
			}
			_gun = null;
			_gunColliders = null;
		}

		private void Ignore(bool ignore)
		{
			if (_roundColliders == null || _gunColliders == null)
			{
				return;
			}
			for (int i = 0; i < _roundColliders.Length; i++)
			{
				Collider val = _roundColliders[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				for (int j = 0; j < _gunColliders.Length; j++)
				{
					Collider val2 = _gunColliders[j];
					if (!((Object)(object)val2 == (Object)null))
					{
						Physics.IgnoreCollision(val, val2, ignore);
					}
				}
			}
		}

		private static Collider[] CollectPhysColliders(GameObject root)
		{
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			List<Collider> list = new List<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !val.isTrigger)
				{
					list.Add(val);
				}
			}
			return list.ToArray();
		}
	}
	public sealed class BoltLockMarker : MonoBehaviour
	{
		public bool OriginalValue;
	}
	internal static class ChamberTrigger
	{
		private struct Settings
		{
			public bool Enabled;

			public Vector3 Center;

			public float Radius;

			public float Height;

			public TriggerAxis Axis;
		}

		private const string ChamberTag = "FVRFireArmChamber";

		private const string VisualName = "Niko666_ChamberTriggerVisual";

		private static readonly Color VisualColor = new Color(0.1f, 0.85f, 1f);

		private static readonly Vector3 MinimumVisualScale = new Vector3(0.001f, 0.001f, 0.001f);

		private static readonly string[] CandidateShaders = new string[4] { "Unlit/Transparent", "Legacy Shaders/Transparent/Diffuse", "Particles/Alpha Blended", "Legacy Shaders/Transparent/VertexLit" };

		private static Material _debugMaterial;

		private static int _problemCount;

		private static bool _noShaderLogged;

		private static bool _oddColliderLogged;

		private static readonly List<FVRFireArmRound> OpenedRounds = new List<FVRFireArmRound>();

		private static readonly HashSet<string> OpenedRoundNames = new HashSet<string>();

		private const int MaxOpenedRoundLogs = 10;

		private static readonly Collider[] OverlapBuffer = (Collider[])(object)new Collider[32];

		internal static void Process(FVRFireArmChamber chamber)
		{
			if ((Object)(object)chamber == (Object)null)
			{
				return;
			}
			GameObject gameObject = ((Component)chamber).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return;
			}
			AddChamberTriggerToEveryGun.ConfigSnapshot cfg = AddChamberTriggerToEveryGun.Cfg;
			ChamberTriggerMarker chamberTriggerMarker = gameObject.GetComponent<ChamberTriggerMarker>();
			bool flag = (((Object)(object)chamberTriggerMarker != (Object)null) ? chamberTriggerMarker.HasVanillaCollider : ((Object)(object)gameObject.GetComponent<Collider>() != (Object)null));
			Collider val = (((Object)(object)chamberTriggerMarker != (Object)null) ? chamberTriggerMarker.VanillaCollider : gameObject.GetComponent<Collider>());
			bool hasOverride;
			Settings settings = ResolveSettings(chamber, out hasOverride);
			if (settings.Enabled && (!flag || cfg.IncludeVanillaColliders || hasOverride))
			{
				if ((Object)(object)chamberTriggerMarker == (Object)null)
				{
					chamberTriggerMarker = gameObject.AddComponent<ChamberTriggerMarker>();
					chamberTriggerMarker.HasVanillaCollider = flag;
					chamberTriggerMarker.VanillaCollider = val;
				}
				if (!Acquire(chamber, chamberTriggerMarker))
				{
					return;
				}
				ApplySettings(chamberTriggerMarker, settings);
				AlignChamberRoundType(chamber, chamberTriggerMarker);
			}
			else if ((Object)(object)chamberTriggerMarker != (Object)null && chamberTriggerMarker.Managed)
			{
				Release(chamberTriggerMarker);
			}
			if ((Object)(object)chamberTriggerMarker == (Object)null && cfg.ShowTriggerColliders && cfg.ShowVanillaTriggers && (Object)(object)val != (Object)null && PrimitiveFor(val) >= 0)
			{
				chamberTriggerMarker = gameObject.AddComponent<ChamberTriggerMarker>();
				chamberTriggerMarker.HasVanillaCollider = true;
				chamberTriggerMarker.VanillaCollider = val;
			}
			SyncVisual(chamberTriggerMarker, cfg);
		}

		internal static void ApplyToAllChambers()
		{
			//IL_003e: 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)
			try
			{
				AddChamberTriggerToEveryGun.ConfigSnapshot cfg = AddChamberTriggerToEveryGun.Cfg;
				FVRFireArmChamber[] array = Resources.FindObjectsOfTypeAll<FVRFireArmChamber>();
				if (array == null)
				{
					return;
				}
				int num = 0;
				foreach (FVRFireArmChamber val in array)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					GameObject gameObject = ((Component)val).gameObject;
					if (!((Object)(object)gameObject == (Object)null))
					{
						Scene scene = gameObject.scene;
						if (((Scene)(ref scene)).IsValid())
						{
							Process(val);
							num++;
						}
					}
				}
				if (cfg.Verbose)
				{
					Log("Chamber triggers updated on " + num + " live chamber(s).");
				}
			}
			catch (Exception ex)
			{
				ReportProblem("Updating every chamber failed", ex);
			}
		}

		internal static void PublishAccessibility(ClosedBolt bolt)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			if (AddChamberTriggerToEveryGun.Cfg.Enabled && AddChamberTriggerToEveryGun.Cfg.ClosedBoltAccessibility && !((Object)(object)bolt == (Object)null) && !((Object)(object)bolt.Weapon == (Object)null))
			{
				FVRFireArmChamber chamber = bolt.Weapon.Chamber;
				if (!((Object)(object)chamber == (Object)null))
				{
					chamber.IsAccessible = (int)bolt.CurPos > 0;
				}
			}
		}

		internal static void PublishAccessibility(AttachableClosedBolt bolt)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			if (AddChamberTriggerToEveryGun.Cfg.Enabled && AddChamberTriggerToEveryGun.Cfg.ClosedBoltAccessibility && !((Object)(object)bolt == (Object)null) && !((Object)(object)bolt.Weapon == (Object)null))
			{
				FVRFireArmChamber chamber = bolt.Weapon.Chamber;
				if (!((Object)(object)chamber == (Object)null))
				{
					chamber.IsAccessible = (int)bolt.CurPos > 0;
				}
			}
		}

		internal static void ResetClosedBoltAccessibility()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ClosedBolt[] array = Resources.FindObjectsOfTypeAll<ClosedBolt>();
				Scene scene;
				if (array != null)
				{
					foreach (ClosedBolt val in array)
					{
						if (!((Object)(object)val == (Object)null))
						{
							scene = ((Component)val).gameObject.scene;
							if (((Scene)(ref scene)).IsValid() && !((Object)(object)val.Weapon == (Object)null) && !((Object)(object)val.Weapon.Chamber == (Object)null))
							{
								val.Weapon.Chamber.IsAccessible = false;
							}
						}
					}
				}
				AttachableClosedBolt[] array2 = Resources.FindObjectsOfTypeAll<AttachableClosedBolt>();
				if (array2 == null)
				{
					return;
				}
				foreach (AttachableClosedBolt val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						scene = ((Component)val2).gameObject.scene;
						if (((Scene)(ref scene)).IsValid() && !((Object)(object)val2.Weapon == (Object)null) && !((Object)(object)val2.Weapon.Chamber == (Object)null))
						{
							val2.Weapon.Chamber.IsAccessible = false;
						}
					}
				}
			}
			catch (Exception ex)
			{
				ReportProblem("Putting closed bolt chambers back out of reach failed", ex);
			}
		}

		private static bool Acquire(FVRFireArmChamber chamber, ChamberTriggerMarker marker)
		{
			if ((Object)(object)marker.Driver != (Object)null)
			{
				marker.Managed = true;
				marker.Driver.enabled = true;
				return true;
			}
			GameObject gameObject = ((Component)chamber).gameObject;
			if (marker.HasVanillaCollider)
			{
				Collider vanillaCollider = marker.VanillaCollider;
				if (!((Object)(object)vanillaCollider == (Object)null))
				{
					if (!IsResizable(vanillaCollider))
					{
						LogOddCollider(chamber, vanillaCollider);
						return false;
					}
					SaveOriginals(marker, chamber, vanillaCollider);
					marker.Driver = vanillaCollider;
					marker.Adopted = true;
					marker.Managed = true;
					TagAsChamber(gameObject);
					chamber.IsManuallyChamberable = true;
					if (AddChamberTriggerToEveryGun.Cfg.Verbose)
					{
						Log("Took over the chamber trigger the game gave " + Describe(gameObject.transform));
					}
					return true;
				}
				marker.HasVanillaCollider = false;
			}
			if ((Object)(object)gameObject.GetComponent<Collider>() != (Object)null)
			{
				return false;
			}
			CapsuleCollider val = gameObject.AddComponent<CapsuleCollider>();
			((Collider)val).isTrigger = true;
			SaveOriginals(marker, chamber, null);
			marker.Driver = (Collider)(object)val;
			marker.Adopted = false;
			marker.Managed = true;
			TagAsChamber(gameObject);
			chamber.IsManuallyChamberable = true;
			if (AddChamberTriggerToEveryGun.Cfg.Verbose)
			{
				Log("Added a chamber trigger to " + Describe(gameObject.transform));
			}
			return true;
		}

		private static void ApplySettings(ChamberTriggerMarker marker, Settings settings)
		{
			//IL_0036: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			Collider driver = marker.Driver;
			if ((Object)(object)driver == (Object)null)
			{
				return;
			}
			driver.enabled = settings.Enabled;
			CapsuleCollider val = (CapsuleCollider)(object)((driver is CapsuleCollider) ? driver : null);
			if ((Object)(object)val != (Object)null)
			{
				((Collider)val).isTrigger = true;
				val.center = settings.Center;
				val.direction = ResolveAxis(settings.Axis, val, marker.Adopted);
				val.radius = settings.Radius;
				val.height = settings.Height;
				return;
			}
			SphereCollider val2 = (SphereCollider)(object)((driver is SphereCollider) ? driver : null);
			if ((Object)(object)val2 != (Object)null)
			{
				((Collider)val2).isTrigger = true;
				val2.center = settings.Center;
				val2.radius = settings.Radius;
				return;
			}
			BoxCollider val3 = (BoxCollider)(object)((driver is BoxCollider) ? driver : null);
			if ((Object)(object)val3 != (Object)null)
			{
				((Collider)val3).isTrigger = true;
				val3.center = settings.Center;
				val3.size = ResolveBoxSize(val3.size, settings);
			}
		}

		internal static void AlignChamberRoundType(FVRFireArmChamber chamber, ChamberTriggerMarker marker)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected I4, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected I4, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!AddChamberTriggerToEveryGun.Cfg.FixChamberRoundType)
				{
					if (marker.RoundTypeSaved)
					{
						chamber.RoundType = marker.OriginalRoundType;
						marker.RoundTypeSaved = false;
						if (AddChamberTriggerToEveryGun.Cfg.Verbose)
						{
							Log("Put the round type of " + Describe(((Component)chamber).transform) + " back to " + (int)marker.OriginalRoundType + ".");
						}
					}
					return;
				}
				int num = DeclaredRoundType(chamber);
				int num2 = (int)chamber.RoundType;
				if (num > 0 && num != num2 && IsKnownRoundType(num))
				{
					if (!marker.RoundTypeSaved)
					{
						marker.RoundTypeSaved = true;
						marker.OriginalRoundType = chamber.RoundType;
					}
					chamber.RoundType = (FireArmRoundType)num;
					if (AddChamberTriggerToEveryGun.Cfg.Verbose)
					{
						Log("The chamber of " + Describe(((Component)chamber).transform) + " was marked round type " + num2 + ", which is not what the gun takes; it now takes " + num + ", the ammo its gun and magazine declare.");
					}
				}
			}
			catch (Exception ex)
			{
				ReportProblem("Making a chamber take its gun's ammo failed", ex);
			}
		}

		private static int DeclaredRoundType(FVRFireArmChamber chamber)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected I4, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected I4, but got Unknown
			FVRFireArm val = chamber.Firearm;
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)chamber).GetComponentInParent<FVRFireArm>();
			}
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			if (!((Object)(object)val.Magazine != (Object)null))
			{
				return (int)val.RoundType;
			}
			return (int)val.Magazine.RoundType;
		}

		private static bool IsKnownRoundType(int roundType)
		{
			try
			{
				List<FireArmRoundType> sTypeList = AM.STypeList;
				if (sTypeList == null || sTypeList.Count == 0)
				{
					return false;
				}
				return sTypeList.Contains((FireArmRoundType)roundType);
			}
			catch (Exception)
			{
				return false;
			}
		}

		private static void Release(ChamberTriggerMarker marker)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			Collider driver = marker.Driver;
			marker.Managed = false;
			if ((Object)(object)driver != (Object)null)
			{
				if (marker.Adopted)
				{
					SetCenter(driver, marker.OriginalCenter);
					driver.isTrigger = marker.OriginalIsTrigger;
					driver.enabled = marker.OriginalEnabled;
					CapsuleCollider val = (CapsuleCollider)(object)((driver is CapsuleCollider) ? driver : null);
					SphereCollider val2 = (SphereCollider)(object)((driver is SphereCollider) ? driver : null);
					BoxCollider val3 = (BoxCollider)(object)((driver is BoxCollider) ? driver : null);
					if ((Object)(object)val != (Object)null)
					{
						val.radius = marker.OriginalRadius;
						val.height = marker.OriginalHeight;
						val.direction = marker.OriginalCapsuleDirection;
					}
					else if ((Object)(object)val2 != (Object)null)
					{
						val2.radius = marker.OriginalRadius;
					}
					else if ((Object)(object)val3 != (Object)null)
					{
						val3.size = marker.OriginalBoxSize;
					}
					marker.Adopted = false;
				}
				else
				{
					driver.enabled = false;
				}
			}
			FVRFireArmChamber component = ((Component)marker).gameObject.GetComponent<FVRFireArmChamber>();
			if ((Object)(object)component != (Object)null && marker.OriginalsSaved)
			{
				component.IsManuallyChamberable = marker.OriginalManuallyChamberable;
				if (marker.RoundTypeSaved)
				{
					component.RoundType = marker.OriginalRoundType;
					marker.RoundTypeSaved = false;
				}
			}
			if (marker.OriginalsSaved && !string.IsNullOrEmpty(marker.OriginalTag))
			{
				try
				{
					((Component)marker).gameObject.tag = marker.OriginalTag;
				}
				catch (Exception)
				{
				}
			}
			DropVisual(marker);
			if (AddChamberTriggerToEveryGun.Cfg.Verbose)
			{
				Log("Let go of the chamber trigger of " + Describe(((Component)marker).transform));
			}
		}

		private static void SaveOriginals(ChamberTriggerMarker marker, FVRFireArmChamber chamber, Collider vanilla)
		{
			//IL_0045: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if (marker.OriginalsSaved)
			{
				return;
			}
			marker.OriginalsSaved = true;
			marker.OriginalManuallyChamberable = chamber.IsManuallyChamberable;
			try
			{
				marker.OriginalTag = ((Component)chamber).gameObject.tag;
			}
			catch (Exception)
			{
				marker.OriginalTag = null;
			}
			if ((Object)(object)vanilla == (Object)null)
			{
				return;
			}
			marker.OriginalCenter = GetCenter(vanilla);
			marker.OriginalIsTrigger = vanilla.isTrigger;
			marker.OriginalEnabled = vanilla.enabled;
			CapsuleCollider val = (CapsuleCollider)(object)((vanilla is CapsuleCollider) ? vanilla : null);
			if ((Object)(object)val != (Object)null)
			{
				marker.OriginalRadius = val.radius;
				marker.OriginalHeight = val.height;
				marker.OriginalCapsuleDirection = val.direction;
				return;
			}
			SphereCollider val2 = (SphereCollider)(object)((vanilla is SphereCollider) ? vanilla : null);
			if ((Object)(object)val2 != (Object)null)
			{
				marker.OriginalRadius = val2.radius;
				return;
			}
			BoxCollider val3 = (BoxCollider)(object)((vanilla is BoxCollider) ? vanilla : null);
			if ((Object)(object)val3 != (Object)null)
			{
				marker.OriginalBoxSize = val3.size;
			}
		}

		private static Settings ResolveSettings(FVRFireArmChamber chamber, out bool hasOverride)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			AddChamberTriggerToEveryGun.ConfigSnapshot cfg = AddChamberTriggerToEveryGun.Cfg;
			Settings result = new Settings
			{
				Enabled = cfg.Enabled,
				Center = cfg.Center,
				Radius = cfg.Radius,
				Height = cfg.Height,
				Axis = cfg.Axis
			};
			hasOverride = false;
			string text = ResolveWeaponKey(chamber);
			if (string.IsNullOrEmpty(text))
			{
				return result;
			}
			if (cfg.Verbose)
			{
				WeaponOverrides.LogKey(text);
			}
			WeaponOverride weaponOverride = WeaponOverrides.Find(text);
			if (weaponOverride == null)
			{
				return result;
			}
			hasOverride = true;
			if (cfg.Verbose)
			{
				WeaponOverrides.LogApplied(text);
			}
			if (weaponOverride.Enabled.HasValue)
			{
				result.Enabled = cfg.Enabled && weaponOverride.Enabled.Value;
			}
			if (weaponOverride.CenterX.HasValue)
			{
				result.Center.x = AddChamberTriggerToEveryGun.Sanitize(weaponOverride.CenterX.Value, result.Center.x);
			}
			if (weaponOverride.CenterY.HasValue)
			{
				result.Center.y = AddChamberTriggerToEveryGun.Sanitize(weaponOverride.CenterY.Value, result.Center.y);
			}
			if (weaponOverride.CenterZ.HasValue)
			{
				result.Center.z = AddChamberTriggerToEveryGun.Sanitize(weaponOverride.CenterZ.Value, result.Center.z);
			}
			if (weaponOverride.Radius.HasValue)
			{
				result.Radius = AddChamberTriggerToEveryGun.ClampRadius(AddChamberTriggerToEveryGun.Sanitize(weaponOverride.Radius.Value, result.Radius));
			}
			if (weaponOverride.Height.HasValue)
			{
				result.Height = AddChamberTriggerToEveryGun.ClampHeight(AddChamberTriggerToEveryGun.Sanitize(weaponOverride.Height.Value, result.Height));
			}
			if (weaponOverride.Direction.HasValue)
			{
				result.Axis = weaponOverride.Direction.Value;
			}
			return result;
		}

		private static string ResolveWeaponKey(FVRFireArmChamber chamber)
		{
			try
			{
				FVRFireArm val = chamber.Firearm;
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)chamber).GetComponentInParent<FVRFireArm>();
				}
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				if ((Object)(object)((FVRPhysicalObject)val).ObjectWrapper != (Object)null && !string.IsNullOrEmpty(((FVRPhysicalObject)val).ObjectWrapper.ItemID))
				{
					return ((FVRPhysicalObject)val).ObjectWrapper.ItemID;
				}
				string text = ((Object)((Component)val).gameObject).name;
				if (string.IsNullOrEmpty(text))
				{
					return null;
				}
				if (text.EndsWith("(Clone)", StringComparison.Ordinal))
				{
					text = text.Substring(0, text.Length - "(Clone)".Length);
				}
				return text;
			}
			catch (Exception)
			{
				return null;
			}
		}

		private static int ResolveAxis(TriggerAxis axis, CapsuleCollider capsule, bool adopted)
		{
			if (axis != TriggerAxis.Auto)
			{
				return (int)axis;
			}
			if (!adopted)
			{
				return 2;
			}
			return capsule.direction;
		}

		private static Vector3 ResolveBoxSize(Vector3 current, Settings settings)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			int axis = ((settings.Axis == TriggerAxis.Auto) ? LongestAxis(current) : ((int)settings.Axis));
			float num = settings.Radius * 2f;
			Vector3 vector = default(Vector3);
			((Vector3)(ref vector))..ctor(num, num, num);
			SetComponent(ref vector, axis, settings.Height);
			return vector;
		}

		private static int LongestAxis(Vector3 size)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			float num = Mathf.Abs(size.x);
			float num2 = Mathf.Abs(size.y);
			float num3 = Mathf.Abs(size.z);
			if (num >= num2 && num >= num3)
			{
				return 0;
			}
			if (!(num2 >= num3))
			{
				return 2;
			}
			return 1;
		}

		private static void SetComponent(ref Vector3 vector, int axis, float value)
		{
			switch (axis)
			{
			case 0:
				vector.x = value;
				break;
			case 1:
				vector.y = value;
				break;
			default:
				vector.z = value;
				break;
			}
		}

		private static Vector3 GetCenter(Collider collider)
		{
			//IL_0011: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider val = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.center;
			}
			SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.center;
			}
			BoxCollider val3 = (BoxCollider)(object)((collider is BoxCollider) ? collider : null);
			if ((Object)(object)val3 != (Object)null)
			{
				return val3.center;
			}
			return Vector3.zero;
		}

		private static void SetCenter(Collider collider, Vector3 center)
		{
			//IL_0011: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider val = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null);
			if ((Object)(object)val != (Object)null)
			{
				val.center = center;
				return;
			}
			SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.center = center;
				return;
			}
			BoxCollider val3 = (BoxCollider)(object)((collider is BoxCollider) ? collider : null);
			if ((Object)(object)val3 != (Object)null)
			{
				val3.center = center;
			}
		}

		private static bool IsResizable(Collider collider)
		{
			if (!(collider is CapsuleCollider) && !(collider is SphereCollider))
			{
				return collider is BoxCollider;
			}
			return true;
		}

		private static void LogOddCollider(FVRFireArmChamber chamber, Collider collider)
		{
			if (!_oddColliderLogged)
			{
				_oddColliderLogged = true;
				Log("A chamber trigger of a type that has no size (a " + ((object)collider).GetType().Name + " on " + Describe(((Component)chamber).transform) + ") was left alone. Only capsule, sphere and box triggers can be resized.");
			}
		}

		private static void TagAsChamber(GameObject go)
		{
			try
			{
				if (go.tag != "FVRFireArmChamber")
				{
					go.tag = "FVRFireArmChamber";
				}
			}
			catch (Exception ex)
			{
				ReportProblem("Could not tag a chamber object as FVRFireArmChamber", ex);
			}
		}

		internal static void WatchHeldRound(FVRFireArmRound round)
		{
			if ((Object)(object)round == (Object)null || (Object)(object)((Component)round).gameObject == (Object)null)
			{
				return;
			}
			AddChamberTriggerToEveryGun.ConfigSnapshot cfg = AddChamberTriggerToEveryGun.Cfg;
			if (cfg.Enabled)
			{
				if (cfg.HandFeedAnyRound)
				{
					AllowHandFeeding(round);
				}
				if (cfg.HeldRoundPassThrough && (Object)(object)((Component)round).gameObject.GetComponent<HeldRoundPassThrough>() == (Object)null)
				{
					((Component)round).gameObject.AddComponent<HeldRoundPassThrough>();
				}
			}
		}

		internal static void AllowHandFeeding(FVRFireArmRound round)
		{
			if (round.isManuallyChamberable)
			{
				return;
			}
			round.isManuallyChamberable = true;
			for (int i = 0; i < OpenedRounds.Count; i++)
			{
				if ((Object)(object)OpenedRounds[i] == (Object)(object)round)
				{
					return;
				}
			}
			OpenedRounds.Add(round);
			LogRoundOpened(round);
		}

		internal static void RestoreHandFeeding()
		{
			try
			{
				int num = 0;
				for (int i = 0; i < OpenedRounds.Count; i++)
				{
					FVRFireArmRound val = OpenedRounds[i];
					if (!((Object)(object)val == (Object)null))
					{
						val.isManuallyChamberable = false;
						num++;
					}
				}
				OpenedRounds.Clear();
				OpenedRoundNames.Clear();
				if (AddChamberTriggerToEveryGun.Cfg.Verbose)
				{
					Log("Put hand feeding back on " + num + " round(s) the mod had opened up.");
				}
			}
			catch (Exception ex)
			{
				ReportProblem("Putting hand feeding back on the rounds the mod opened failed", ex);
			}
		}

		private static void LogRoundOpened(FVRFireArmRound round)
		{
			if (AddChamberTriggerToEveryGun.Cfg.Verbose)
			{
				string text;
				try
				{
					text = (((Object)(object)((Component)round).gameObject != (Object)null) ? ((Object)((Component)round).gameObject).name : "a round");
				}
				catch (Exception)
				{
					text = "a round";
				}
				if (OpenedRoundNames.Count < 10 && OpenedRoundNames.Add(text))
				{
					Log("Opened " + text + " for hand feeding: the round itself ships with hand feeding switched off, and a held round ignores every chamber until it is on.");
				}
			}
		}

		internal static bool FindGunToPassThrough(FVRFireArmRound round, float range, out FVRPhysicalObject gun)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			gun = null;
			if (range <= 0f)
			{
				range = 0.05f;
			}
			int num = Physics.OverlapSphereNonAlloc(((Component)round).transform.position, range, OverlapBuffer, -1, (QueryTriggerInteraction)2);
			for (int i = 0; i < num; i++)
			{
				Collider val = OverlapBuffer[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				ChamberTriggerMarker component = ((Component)val).GetComponent<ChamberTriggerMarker>();
				if (!((Object)(object)component == (Object)null) && component.Managed)
				{
					FVRPhysicalObject componentInParent = ((Component)val).GetComponentInParent<FVRPhysicalObject>();
					if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)componentInParent == (Object)(object)round))
					{
						gun = componentInParent;
						return true;
					}
				}
			}
			return false;
		}

		internal static void LogPassThrough(FVRPhysicalObject gun, int roundColliders, int gunColliders)
		{
			Log("Held round pass-through: " + roundColliders + " round collider(s) ignoring " + gunColliders + " collider(s) of " + Describe(((Component)gun).transform));
		}

		internal static void RelaxBoltLockRequirement(OpenBoltReceiverBolt bolt)
		{
			if ((Object)(object)bolt == (Object)null || (Object)(object)((Component)bolt).gameObject == (Object)null || !AddChamberTriggerToEveryGun.Cfg.Enabled || !AddChamberTriggerToEveryGun.Cfg.OpenBoltAccessWithoutLock)
			{
				return;
			}
			if ((Object)(object)((Component)bolt).gameObject.GetComponent<BoltLockMarker>() == (Object)null)
			{
				((Component)bolt).gameObject.AddComponent<BoltLockMarker>().OriginalValue = bolt.IsBoltLockbackRequiredForChamberAccessibility;
			}
			if (bolt.IsBoltLockbackRequiredForChamberAccessibility)
			{
				bolt.IsBoltLockbackRequiredForChamberAccessibility = false;
				if (AddChamberTriggerToEveryGun.Cfg.Verbose)
				{
					Log("Bolt lock requirement removed from " + Describe(((Component)bolt).transform));
				}
			}
		}

		internal static void ResetBoltLockRequirement()
		{
			try
			{
				OpenBoltReceiverBolt[] array = Resources.FindObjectsOfTypeAll<OpenBoltReceiverBolt>();
				if (array == null)
				{
					return;
				}
				foreach (OpenBoltReceiverBolt val in array)
				{
					if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
					{
						BoltLockMarker component = ((Component)val).gameObject.GetComponent<BoltLockMarker>();
						if (!((Object)(object)component == (Object)null))
						{
							val.IsBoltLockbackRequiredForChamberAccessibility = component.OriginalValue;
							Object.Destroy((Object)(object)component);
						}
					}
				}
			}
			catch (Exception ex)
			{
				ReportProblem("Putting the bolt lock requirement back failed", ex);
			}
		}

		private static void SyncVisual(ChamberTriggerMarker marker, AddChamberTriggerToEveryGun.ConfigSnapshot cfg)
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: 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_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)marker == (Object)null)
			{
				return;
			}
			bool num = marker.Managed && (Object)(object)marker.Driver != (Object)null;
			Collider val = null;
			if (num)
			{
				val = marker.Driver;
			}
			else if (cfg.ShowVanillaTriggers)
			{
				val = marker.VanillaCollider;
			}
			int num2 = (cfg.ShowTriggerColliders ? PrimitiveFor(val) : (-1));
			if (num2 < 0)
			{
				DropVisual(marker);
				return;
			}
			if ((Object)(object)marker.Visual == (Object)null || marker.VisualPrimitive != num2)
			{
				DropVisual(marker);
				marker.Visual = CreateVisual(((Component)marker).transform);
				marker.VisualPrimitive = (((Object)(object)marker.Visual == (Object)null) ? (-1) : num2);
				if ((Object)(object)marker.Visual == (Object)null)
				{
					return;
				}
			}
			if ((Object)(object)_debugMaterial != (Object)null)
			{
				SetDebugAlpha(_debugMaterial, cfg.DebugAlpha);
			}
			Transform transform = marker.Visual.transform;
			transform.localPosition = GetCenter(val);
			CapsuleCollider val2 = (CapsuleCollider)(object)((val is CapsuleCollider) ? val : null);
			if ((Object)(object)val2 != (Object)null)
			{
				transform.localRotation = CapsuleRotation(val2.direction);
				transform.localScale = Fit(new Vector3(val2.radius * 2f, val2.height * 0.5f, val2.radius * 2f));
				return;
			}
			SphereCollider val3 = (SphereCollider)(object)((val is SphereCollider) ? val : null);
			if ((Object)(object)val3 != (Object)null)
			{
				transform.localRotation = Quaternion.identity;
				transform.localScale = Fit(new Vector3(val3.radius * 2f, val3.radius * 2f, val3.radius * 2f));
				return;
			}
			BoxCollider val4 = (BoxCollider)(object)((val is BoxCollider) ? val : null);
			if ((Object)(object)val4 != (Object)null)
			{
				transform.localRotation = Quaternion.identity;
				transform.localScale = Fit(val4.size);
			}
		}

		private static int PrimitiveFor(Collider collider)
		{
			if (collider is CapsuleCollider)
			{
				return 1;
			}
			if (collider is SphereCollider)
			{
				return 0;
			}
			if (collider is BoxCollider)
			{
				return 3;
			}
			return -1;
		}

		private static Quaternion CapsuleRotation(int direction)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			return (Quaternion)(direction switch
			{
				0 => Quaternion.Euler(0f, 0f, 90f), 
				2 => Quaternion.Euler(90f, 0f, 0f), 
				_ => Quaternion.identity, 
			});
		}

		private static Vector3 Fit(Vector3 scale)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			scale.x = Mathf.Max(Mathf.Abs(scale.x), MinimumVisualScale.x);
			scale.y = Mathf.Max(Mathf.Abs(scale.y), MinimumVisualScale.y);
			scale.z = Mathf.Max(Mathf.Abs(scale.z), MinimumVisualScale.z);
			return scale;
		}

		private static void DropVisual(ChamberTriggerMarker marker)
		{
			if ((Object)(object)marker.Visual != (Object)null)
			{
				Object.Destroy((Object)(object)marker.Visual);
			}
			marker.Visual = null;
			marker.VisualPrimitive = -1;
		}

		private static GameObject CreateVisual(Transform parent)
		{
			try
			{
				Material debugMaterial = GetDebugMaterial(AddChamberTriggerToEveryGun.Cfg.DebugAlpha);
				if ((Object)(object)debugMaterial == (Object)null)
				{
					return null;
				}
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)1);
				((Object)obj).name = "Niko666_ChamberTriggerVisual";
				obj.layer = ((Component)parent).gameObject.layer;
				Collider component = obj.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					component.enabled = false;
					Object.Destroy((Object)(object)component);
				}
				MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Renderer)component2).sharedMaterial = debugMaterial;
					((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)component2).receiveShadows = false;
				}
				obj.transform.SetParent(parent, false);
				return obj;
			}
			catch (Exception ex)
			{
				ReportProblem("Could not build the debug capsule", ex);
				return null;
			}
		}

		private static Material GetDebugMaterial(float alpha)
		{
			//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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_006e: Expected O, but got Unknown
			if ((Object)(object)_debugMaterial != (Object)null)
			{
				SetDebugAlpha(_debugMaterial, alpha);
				return _debugMaterial;
			}
			Shader val = FindTransparentShader();
			if ((Object)(object)val == (Object)null)
			{
				if (!_noShaderLogged)
				{
					_noShaderLogged = true;
					Log("No transparent shader is available in this game build, so the debug view stays empty. Everything else still works.");
				}
				return null;
			}
			Material val2 = new Material(val)
			{
				name = "Niko666_ChamberTriggerDebug",
				renderQueue = 3000
			};
			_debugMaterial = val2;
			SetDebugAlpha(val2, alpha);
			return _debugMaterial;
		}

		private static void SetDebugAlpha(Material material, float alpha)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			((Color)(ref val))..ctor(VisualColor.r, VisualColor.g, VisualColor.b, alpha);
			if (material.HasProperty("_Color"))
			{
				material.color = val;
			}
			else if (material.HasProperty("_TintColor"))
			{
				material.SetColor("_TintColor", val);
			}
			else if (material.HasProperty("_MainTex"))
			{
				Texture mainTexture = material.mainTexture;
				Texture2D val2 = (Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null);
				if ((Object)(object)val2 == (Object)null)
				{
					material.mainTexture = (Texture)(object)CreateAlphaTexture(alpha);
					return;
				}
				val2.SetPixel(0, 0, val);
				val2.Apply();
			}
		}

		private static Texture2D CreateAlphaTexture(float alpha)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_003c: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1, (TextureFormat)5, false);
			val.SetPixel(0, 0, new Color(VisualColor.r, VisualColor.g, VisualColor.b, alpha));
			val.Apply();
			return val;
		}

		private static Shader FindTransparentShader()
		{
			for (int i = 0; i < CandidateShaders.Length; i++)
			{
				Shader val = Shader.Find(CandidateShaders[i]);
				if ((Object)(object)val != (Object)null && HasColorSlot(val))
				{
					Log("Debug shapes are drawn with the shader " + ((Object)val).name + ".");
					return val;
				}
			}
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(Material));
			if (array != null)
			{
				foreach (Object obj in array)
				{
					Material val2 = (Material)(object)((obj is Material) ? obj : null);
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.shader == (Object)null) && val2.shader.renderQueue >= 3000 && (val2.HasProperty("_Color") || val2.HasProperty("_TintColor")))
					{
						Log("Debug shapes are drawn with the shader " + ((Object)val2.shader).name + " (borrowed from " + ((Object)val2).name + ").");
						return val2.shader;
					}
				}
			}
			return null;
		}

		private static bool HasColorSlot(Shader shader)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			Material val = null;
			try
			{
				val = new Material(shader);
				return val.HasProperty("_Color") || val.HasProperty("_TintColor") || val.HasProperty("_MainTex");
			}
			catch (Exception)
			{
				return false;
			}
			finally
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static string Describe(Transform t)
		{
			try
			{
				return ((Object)t.root).name + "/" + ((Object)t).name;
			}
			catch (Exception)
			{
				return "a chamber";
			}
		}

		internal static void ReportProblem(string message, Exception ex)
		{
			if (_problemCount < 5)
			{
				_problemCount++;
				if (AddChamberTriggerToEveryGun.Logger != null)
				{
					AddChamberTriggerToEveryGun.Logger.LogWarning((object)(message + ": " + ex));
				}
			}
		}

		private static void Log(string message)
		{
			AddChamberTriggerToEveryGun.LogInfo(message);
		}
	}
	[BepInProcess("h3vr.exe")]
	[BepInPlugin("Niko666.AddChamberTriggerToEveryGun", "AddChamberTriggerToEveryGun", "1.0.1")]
	public class AddChamberTriggerToEveryGun : BaseUnityPlugin
	{
		internal struct ConfigSnapshot
		{
			public bool Enabled;

			public Vector3 Center;

			public float Radius;

			public float Height;

			public TriggerAxis Axis;

			public bool IncludeVanillaColliders;

			public bool ClosedBoltAccessibility;

			public bool HeldRoundPassThrough;

			public float HeldRoundPassRange;

			public bool OpenBoltAccessWithoutLock;

			public bool HandFeedAnyRound;

			public bool FixChamberRoundType;

			public bool ShowTriggerColliders;

			public bool ShowVanillaTriggers;

			public float DebugAlpha;

			public bool Verbose;
		}

		public static ConfigEntry<bool> ModEnabled;

		public static ConfigEntry<float> CenterX;

		public static ConfigEntry<float> CenterY;

		public static ConfigEntry<float> CenterZ;

		public static ConfigEntry<float> TriggerRadius;

		public static ConfigEntry<float> TriggerHeight;

		public static ConfigEntry<TriggerAxis> Direction;

		public static ConfigEntry<bool> IncludeVanillaColliders;

		public static ConfigEntry<bool> ClosedBoltAccessibility;

		public static ConfigEntry<bool> HeldRoundPassThrough;

		public static ConfigEntry<float> HeldRoundPassRange;

		public static ConfigEntry<bool> OpenBoltAccessWithoutLock;

		public static ConfigEntry<bool> HandFeedAnyRound;

		public static ConfigEntry<bool> FixChamberRoundType;

		public static ConfigEntry<bool> DebugShowTriggers;

		public static ConfigEntry<bool> DebugShowVanillaTriggers;

		public static ConfigEntry<float> DebugAlpha;

		public static ConfigEntry<bool> VerboseLogging;

		private const float DefaultCenterX = 0f;

		private const float DefaultCenterY = 0f;

		private const float DefaultCenterZ = -0.03f;

		private const float DefaultRadius = 0.011f;

		private const float DefaultHeight = 0.13f;

		private const float DefaultAlpha = 0.35f;

		internal static ConfigSnapshot Cfg;

		private static bool _closedBoltWasDriven;

		private static bool _openBoltWasDriven;

		private static bool _handFeedWasDriven;

		private static bool _applyPending;

		private static string _configFilePath;

		private static long _configFileStamp = -1L;

		private static float _lastConfigCheck;

		private int _updateErrors;

		public const string Id = "Niko666.AddChamberTriggerToEveryGun";

		public static AddChamberTriggerToEveryGun Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		public static string Name => "AddChamberTriggerToEveryGun";

		public static string Version => "1.0.1";

		private void BindConfig()
		{
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. Off: no chamber gets a loading trigger, a gun that was taken over gets its own trigger back exactly as it was, and every trigger this mod added is switched off. Takes effect immediately, no scene reload or restart.");
			CenterX = ((BaseUnityPlugin)this).Config.Bind<float>("Chamber Trigger", "CenterX", 0f, "Where the trigger sits on the chamber's local X axis, in meters (left/right).");
			CenterY = ((BaseUnityPlugin)this).Config.Bind<float>("Chamber Trigger", "CenterY", 0f, "Where the trigger sits on the chamber's local Y axis, in meters (up/down).");
			CenterZ = ((BaseUnityPlugin)this).Config.Bind<float>("Chamber Trigger", "CenterZ", -0.03f, "Where the trigger sits on the chamber's local Z axis, in meters. Negative moves it back toward the shooter; the chamber's forward axis points down the barrel on most guns.");
			TriggerRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Chamber Trigger", "Radius", 0.011f, "Radius of the capsule a round has to touch to be taken in, in meters (0.001-0.2).");
			TriggerHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Chamber Trigger", "Height", 0.13f, "Length of that capsule, in meters (0.001-1). The longer it is, the less precisely the round has to be lined up with the chamber.");
			Direction = ((BaseUnityPlugin)this).Config.Bind<TriggerAxis>("Chamber Trigger", "Direction", TriggerAxis.Auto, "Which way the trigger runs along the chamber. Auto = Z for a trigger this mod adds (the case's long axis), and the axis the gun's own trigger already had when taking one over. X, Y or Z forces that axis on both.");
			IncludeVanillaColliders = ((BaseUnityPlugin)this).Config.Bind<bool>("Chamber Trigger", "IncludeVanillaColliders", false, "Off: only chambers with no trigger of their own get one, and the guns the game tuned itself stay exactly as they are. On: a chamber that already has a trigger is taken over as well - its collider is moved and resized by the settings above, it is tagged and made manually chamberable, and it is put back the way the game had it the moment this is switched off. The values above are tuned for guns that have no trigger at all, so a gun that already works can get worse; turn this on to fix specific guns, not as a blanket setting (a weapon entry in the JSON file takes over its gun whichever way this is set).");
			ClosedBoltAccessibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Chamber Trigger", "ClosedBoltAccessibility", true, "On: guns whose action never tells the game whether the chamber is reachable (every AK, AR, FAL and friends - FistVR.ClosedBolt) get the same rule a pistol already uses, the chamber is out of reach while the bolt is all the way forward and reachable as soon as it comes back. Without this a loose round that touches the trigger is refused by the game and nothing happens on those guns. Off: the trigger is still added and drawn, but the gun behaves exactly as it does in vanilla, where those guns cannot be hand loaded at all.");
			HeldRoundPassThrough = ((BaseUnityPlugin)this).Config.Bind<bool>("Chamber Trigger", "HeldRoundPassThrough", true, "On: while you are holding a round, a gun this mod gave a trigger to stops blocking it as soon as the round comes within HeldRoundPassRange of that trigger, so the round can be pushed through the frame into the chamber instead of being stopped by it. Only that one gun is affected, only while the round is held and close, and only its frame - every trigger on it, the chamber first, keeps working exactly as it did. Off: rounds collide with guns the way they always have.");
			HeldRoundPassRange = ((BaseUnityPlugin)this).Config.Bind<float>("Chamber Trigger", "HeldRoundPassRange", 0.15f, "How close (in meters) a held round has to be to a trigger this mod added before the gun stops blocking it (0.01-1). Smaller means the round has to be lined up with the chamber more precisely first; larger means it starts going through the gun from further away.");
			OpenBoltAccessWithoutLock = ((BaseUnityPlugin)this).Config.Bind<bool>("Chamber Trigger", "OpenBoltAccessWithoutLock", true, "On: open bolt guns (Sten, MP40, Uzi and friends) open their chamber for a hand fed round as soon as the bolt is not all the way forward - the rule the rest of the game uses - instead of insisting the bolt be held on its catch. Off: the gun's own flag (FistVR.OpenBoltReceiverBolt.IsBoltLockbackRequiredForChamberAccessibility) is left at whatever its prefab says.");
			HandFeedAnyRound = ((BaseUnityPlugin)this).Config.Bind<bool>("Chamber Trigger", "HandFeedAnyRound", true, "On: rounds the game itself refuses to hand feed are opened up while you are holding one, so the guns they belong to (MP7A1, P90 and Five-seveN, QBZ95 and a few oddities) can be hand loaded like everything else. The gate is on the round, not the gun: a held round only starts looking at chambers at all while its own FistVR.FVRFireArmRound.isManuallyChamberable is true, and 28 of the game's round prefabs ship with it false - every 4.6x30mm (MP7A1), 5.7x28mm (P90, Five-seveN), 5.8x42mm (QBZ95), 4.7x33mm, 8mm Bergmann, 5mm Bergmann, 8mm Roth-Steyr, .38 ACP, 9x23mm Steyr, .36 Moses, .46 Ball, 2x50mm Caseless and aCpbp round. Without this those guns go on refusing a round that is sitting right on their trigger, whatever the chamber is set to. Only the round the mod is actually holding is touched, and every one of them is put back when this (or the master switch) is switched off.");
			FixChamberRoundType = ((BaseUnityPlugin)this).Config.Bind<bool>("Chamber Trigger", "FixChamberRoundType", true, "On: a chamber whose round type disagrees with the ammo its own gun takes is set to the gun's. The QBZ95 is the gun this was found on: its rifle and every magazine for it say 5.8x42mm, while the chamber in its prefab says 5.56x45mm, and a round only offers itself to a chamber while the two agree - so a 5.8x42mm round was turned away before the trigger, the tag or anything else could matter. The gun's own round type is the truth here (or the magazine's, when one is in it), a chamber is only ever changed when it disagrees with it, and it is only changed to a type the ammo system has; everything is put back when this (or the master switch) is switched off.");
			DebugShowTriggers = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowTriggerColliders", false, "Draw the chamber trigger of every gun this mod handles as a semi transparent shape, so you can see where it sits while you tune the values above.");
			DebugShowVanillaTriggers = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowVanillaTriggers", false, "Extend ShowTriggerColliders to the chambers this mod does not touch, drawn from the collider the game already put there (its real shape, position and size). Useful for seeing where an untouched gun's trigger is, and for comparing it with what the settings above would do.");
			DebugAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Debug", "TriggerAlpha", 0.35f, "How see-through the debug shapes are (0.05-1).");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Log every chamber that is taken over or let go, and every weapon key that is seen (the line reads 'weapon key seen: <ItemID>', which is exactly what a JSON entry has to be keyed by). Turn this on while setting up a JSON entry, then turn it back off.");
			AddSettingChangedListener<bool>(ModEnabled);
			AddSettingChangedListener<float>(CenterX);
			AddSettingChangedListener<float>(CenterY);
			AddSettingChangedListener<float>(CenterZ);
			AddSettingChangedListener<float>(TriggerRadius);
			AddSettingChangedListener<float>(TriggerHeight);
			AddSettingChangedListener<TriggerAxis>(Direction);
			AddSettingChangedListener<bool>(IncludeVanillaColliders);
			AddSettingChangedListener<bool>(ClosedBoltAccessibility);
			AddSettingChangedListener<bool>(HeldRoundPassThrough);
			AddSettingChangedListener<float>(HeldRoundPassRange);
			AddSettingChangedListener<bool>(OpenBoltAccessWithoutLock);
			AddSettingChangedListener<bool>(HandFeedAnyRound);
			AddSettingChangedListener<bool>(FixChamberRoundType);
			AddSettingChangedListener<bool>(DebugShowTriggers);
			AddSettingChangedListener<bool>(DebugShowVanillaTriggers);
			AddSettingChangedListener<float>(DebugAlpha);
			AddSettingChangedListener<bool>(VerboseLogging);
		}

		private static void AddSettingChangedListener<T>(ConfigEntry<T> entry)
		{
			entry.SettingChanged += delegate
			{
				OnConfigChanged();
			};
		}

		private static void OnConfigChanged()
		{
			ReloadConfigSnapshot();
			_applyPending = true;
		}

		private static void ReloadConfigSnapshot()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ConfigSnapshot cfg = DefaultSnapshot();
				cfg.Enabled = ModEnabled.Value;
				cfg.Center = new Vector3(Sanitize(CenterX.Value, 0f), Sanitize(CenterY.Value, 0f), Sanitize(CenterZ.Value, -0.03f));
				cfg.Radius = ClampRadius(Sanitize(TriggerRadius.Value, 0.011f));
				cfg.Height = ClampHeight(Sanitize(TriggerHeight.Value, 0.13f));
				cfg.Axis = Direction.Value;
				cfg.IncludeVanillaColliders = IncludeVanillaColliders.Value;
				cfg.ClosedBoltAccessibility = ClosedBoltAccessibility.Value;
				cfg.HeldRoundPassThrough = HeldRoundPassThrough.Value;
				cfg.HeldRoundPassRange = Mathf.Clamp(Sanitize(HeldRoundPassRange.Value, 0.15f), 0.01f, 1f);
				cfg.OpenBoltAccessWithoutLock = OpenBoltAccessWithoutLock.Value;
				cfg.HandFeedAnyRound = HandFeedAnyRound.Value;
				cfg.FixChamberRoundType = FixChamberRoundType.Value;
				cfg.ShowTriggerColliders = DebugShowTriggers.Value;
				cfg.ShowVanillaTriggers = DebugShowVanillaTriggers.Value;
				cfg.DebugAlpha = Mathf.Clamp(Sanitize(DebugAlpha.Value, 0.35f), 0.05f, 1f);
				cfg.Verbose = VerboseLogging.Value;
				Cfg = cfg;
				bool flag = cfg.Enabled && cfg.ClosedBoltAccessibility;
				if (_closedBoltWasDriven && !flag)
				{
					ChamberTrigger.ResetClosedBoltAccessibility();
				}
				_closedBoltWasDriven = flag;
				bool flag2 = cfg.Enabled && cfg.OpenBoltAccessWithoutLock;
				if (_openBoltWasDriven && !flag2)
				{
					ChamberTrigger.ResetBoltLockRequirement();
				}
				_openBoltWasDriven = flag2;
				bool flag3 = cfg.Enabled && cfg.HandFeedAnyRound;
				if (_handFeedWasDriven && !flag3)
				{
					ChamberTrigger.RestoreHandFeeding();
				}
				_handFeedWasDriven = flag3;
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Could not read the config, keeping the last good values: " + ex.Message));
			}
		}

		private static ConfigSnapshot DefaultSnapshot()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			return new ConfigSnapshot
			{
				Enabled = true,
				Center = new Vector3(0f, 0f, -0.03f),
				Radius = 0.011f,
				Height = 0.13f,
				Axis = TriggerAxis.Auto,
				IncludeVanillaColliders = false,
				ClosedBoltAccessibility = true,
				HeldRoundPassThrough = true,
				HeldRoundPassRange = 0.15f,
				OpenBoltAccessWithoutLock = true,
				HandFeedAnyRound = true,
				FixChamberRoundType = true,
				ShowTriggerColliders = false,
				ShowVanillaTriggers = false,
				DebugAlpha = 0.35f,
				Verbose = false
			};
		}

		internal static float Sanitize(float value, float fallback)
		{
			if (float.IsNaN(value) || float.IsInfinity(value))
			{
				return fallback;
			}
			return value;
		}

		internal static float ClampRadius(float value)
		{
			return Mathf.Clamp(value, 0.0005f, 0.5f);
		}

		internal static float ClampHeight(float value)
		{
			return Mathf.Clamp(value, 0.001f, 1f);
		}

		private static void ReloadFromDisk()
		{
			try
			{
				if ((Object)(object)Instance != (Object)null && ((BaseUnityPlugin)Instance).Config != null)
				{
					((BaseUnityPlugin)Instance).Config.Reload();
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Config reload failed: " + ex.Message));
			}
			ReloadConfigSnapshot();
			RememberConfigFileStamp();
			WeaponOverrides.Reload();
		}

		private static void RememberConfigFileStamp()
		{
			if (string.IsNullOrEmpty(_configFilePath))
			{
				return;
			}
			try
			{
				_configFileStamp = (File.Exists(_configFilePath) ? File.GetLastWriteTimeUtc(_configFilePath).Ticks : (-1));
			}
			catch (Exception)
			{
				_configFileStamp = -1L;
			}
		}

		private static void CheckFilesChanged()
		{
			CheckConfigFileChanged();
			if (WeaponOverrides.CheckFileChanged())
			{
				_applyPending = true;
			}
		}

		private static void CheckConfigFileChanged()
		{
			if (string.IsNullOrEmpty(_configFilePath))
			{
				return;
			}
			try
			{
				if (File.Exists(_configFilePath) && File.GetLastWriteTimeUtc(_configFilePath).Ticks != _configFileStamp)
				{
					Logger.LogMessage((object)"Config file changed on disk, reloading it.");
					ReloadFromDisk();
				}
			}
			catch (Exception)
			{
			}
		}

		public void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Cfg = DefaultSnapshot();
			try
			{
				BindConfig();
				ReloadConfigSnapshot();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Config could not be set up, the mod uses its built in defaults: " + ex));
			}
			try
			{
				_configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			}
			catch (Exception)
			{
				_configFilePath = null;
			}
			RememberConfigFileStamp();
			try
			{
				WeaponOverrides.Init(GetWeaponOverridePath());
			}
			catch (Exception ex3)
			{
				Logger.LogWarning((object)("Weapon override file could not be set up: " + ex3.Message));
			}
			PatchGroup(typeof(ChamberTriggerPatch), "no gun will be given a trigger");
			PatchGroup(typeof(ClosedBoltAccessPatch), "closed bolt guns (AK/AR/FAL) will refuse a hand fed round");
			PatchGroup(typeof(AttachableClosedBoltAccessPatch), "an attached closed bolt gun will refuse a hand fed round");
			PatchGroup(typeof(HeldRoundPassPatch), "a held round cannot be pushed past a gun that is in the way");
			PatchGroup(typeof(OpenBoltLockPatch), "open bolt guns will need the bolt on its catch to take a round");
			try
			{
				SceneManager.sceneLoaded += OnSceneLoaded;
			}
			catch (Exception ex4)
			{
				Logger.LogWarning((object)("Could not listen for scene loads: " + ex4.Message));
			}
			Logger.LogMessage((object)("Hello, world! Sent from Niko666.AddChamberTriggerToEveryGun " + Version));
		}

		public void Update()
		{
			try
			{
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime - _lastConfigCheck >= 1f)
				{
					_lastConfigCheck = unscaledTime;
					CheckFilesChanged();
				}
				if (_applyPending)
				{
					_applyPending = false;
					ChamberTrigger.ApplyToAllChambers();
				}
			}
			catch (Exception ex)
			{
				if (_updateErrors < 3)
				{
					_updateErrors++;
					Logger.LogError((object)("Update failed: " + ex));
				}
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			try
			{
				ReloadFromDisk();
				_applyPending = true;
			}
			catch (Exception ex)
			{
				if (_updateErrors < 3)
				{
					_updateErrors++;
					Logger.LogError((object)("Handling a scene load failed: " + ex));
				}
			}
		}

		private static string GetWeaponOverridePath()
		{
			if (string.IsNullOrEmpty(_configFilePath))
			{
				return null;
			}
			return Path.ChangeExtension(_configFilePath, ".json");
		}

		private void PatchGroup(Type patchClass, string whatBreaksWithoutIt)
		{
			try
			{
				Harmony.CreateAndPatchAll(patchClass, "Niko666.AddChamberTriggerToEveryGun");
				Logger.LogMessage((object)("Patch group applied: " + patchClass.Name));
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Patch group " + patchClass.Name + " failed, " + whatBreaksWithoutIt + ": " + ex));
			}
		}

		internal static void LogInfo(string message)
		{
			if (Logger != null)
			{
				Logger.LogMessage((object)message);
			}
		}
	}
	public enum TriggerAxis
	{
		Auto = -1,
		X,
		Y,
		Z
	}
	public sealed class WeaponOverride
	{
		public float? CenterX { get; set; }

		public float? CenterY { get; set; }

		public float? CenterZ { get; set; }

		public float? Radius { get; set; }

		public float? Height { get; set; }

		[JsonConverter(typeof(StringEnumConverter))]
		public TriggerAxis? Direction { get; set; }

		public bool? Enabled { get; set; }
	}
	public sealed class WeaponOverrideFile
	{
		public Dictionary<string, WeaponOverride> WeaponOverrides { get; set; }
	}
	internal static class WeaponOverrides
	{
		private static readonly Dictionary<string, WeaponOverride> Entries = new Dictionary<string, WeaponOverride>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> LoggedKeys = new HashSet<string>();

		private static readonly HashSet<string> LoggedOverrides = new HashSet<string>();

		private static string _filePath;

		private static long _fileStamp = -1L;

		internal static string FilePath => _filePath;

		internal static int Count => Entries.Count;

		internal static void Init(string filePath)
		{
			_filePath = filePath;
			if (string.IsNullOrEmpty(filePath))
			{
				Log("No weapon override file path, only the .cfg settings are used.");
				return;
			}
			try
			{
				if (!File.Exists(filePath))
				{
					Log("Weapon override file not found, creating an example one at " + filePath);
					CreateExample(filePath);
				}
			}
			catch (Exception ex)
			{
				AddChamberTriggerToEveryGun.Logger.LogWarning((object)("Could not create the weapon override file: " + ex.Message));
			}
			Load();
			RememberStamp();
		}

		internal static bool Reload()
		{
			Load();
			RememberStamp();
			return true;
		}

		internal static bool CheckFileChanged()
		{
			if (string.IsNullOrEmpty(_filePath))
			{
				return false;
			}
			try
			{
				if (!File.Exists(_filePath))
				{
					return false;
				}
				if (File.GetLastWriteTimeUtc(_filePath).Ticks == _fileStamp)
				{
					return false;
				}
				Log("Weapon override file changed on disk, reloading it.");
				Load();
				RememberStamp();
				return true;
			}
			catch (Exception)
			{
				return false;
			}
		}

		internal static WeaponOverride Find(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return null;
			}
			if (!Entries.TryGetValue(key, out var value))
			{
				return null;
			}
			return value;
		}

		internal static void LogKey(string key)
		{
			if (LoggedKeys.Add(key))
			{
				Log("weapon key seen: " + key + "  (use this as the key in the JSON file)");
			}
		}

		internal static void LogApplied(string key)
		{
			if (LoggedOverrides.Add(key))
			{
				Log("weapon override applied: " + key);
			}
		}

		private static void Load()
		{
			Entries.Clear();
			LoggedOverrides.Clear();
			if (string.IsNullOrEmpty(_filePath) || !File.Exists(_filePath))
			{
				return;
			}
			try
			{
				WeaponOverrideFile weaponOverrideFile = JsonConvert.DeserializeObject<WeaponOverrideFile>(File.ReadAllText(_filePath));
				if (weaponOverrideFile == null || weaponOverrideFile.WeaponOverrides == null)
				{
					Log("Weapon override file has no WeaponOverrides section, only the .cfg settings are used.");
					return;
				}
				foreach (KeyValuePair<string, WeaponOverride> weaponOverride in weaponOverrideFile.WeaponOverrides)
				{
					if (!string.IsNullOrEmpty(weaponOverride.Key) && weaponOverride.Value != null)
					{
						Entries[weaponOverride.Key] = weaponOverride.Value;
					}
				}
				Log("Loaded " + Entries.Count + " weapon override(s).");
			}
			catch (Exception ex)
			{
				Entries.Clear();
				AddChamberTriggerToEveryGun.Logger.LogWarning((object)("Weapon override file could not be read, only the .cfg settings are used: " + ex.Message));
			}
		}

		private static void RememberStamp()
		{
			if (string.IsNullOrEmpty(_filePath))
			{
				return;
			}
			try
			{
				_fileStamp = (File.Exists(_filePath) ? File.GetLastWriteTimeUtc(_filePath).Ticks : (-1));
			}
			catch (Exception)
			{
				_fileStamp = -1L;
			}
		}

		private static void CreateExample(string path)
		{
			WeaponOverrideFile weaponOverrideFile = new WeaponOverrideFile();
			weaponOverrideFile.WeaponOverrides = new Dictionary<string, WeaponOverride>();
			weaponOverrideFile.WeaponOverrides["Example_ReplaceWithAWeaponItemID"] = new WeaponOverride
			{
				CenterX = 0f,
				CenterY = 0f,
				CenterZ = -0.03f,
				Radius = 0.011f,
				Height = 0.13f,
				Direction = TriggerAxis.Auto,
				Enabled = true
			};
			File.WriteAllText(path, JsonConvert.SerializeObject((object)weaponOverrideFile, (Formatting)1));
		}

		private static void Log(string message)
		{
			AddChamberTriggerToEveryGun.LogInfo(message);
		}
	}
}