Decompiled source of TurnOffLandmines v1.0.0

BepInEx/plugins/TurnOffLandmines/TurnOffLandmines.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("erockuli")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2026 erockuli")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TurnOffLandmines")]
[assembly: AssemblyTitle("TurnOffLandmines")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 TurnOffLandmines
{
	[BepInPlugin("com.turnofflandmines.plugin", "Turn Off Landmines", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class MineInteraction
		{
			public Landmine Mine;

			public GameObject Zone;

			public SphereCollider Collider;

			public InteractTrigger Trigger;

			public bool Processing;

			public GameObject WarningAudioObject;

			public AudioSource WarningAudioSource;
		}

		public const string ModGuid = "com.turnofflandmines.plugin";

		public const string ModName = "Turn Off Landmines";

		public const string ModVersion = "1.0.0";

		private static Plugin _instance;

		private Harmony _spawnCompatibilityHarmony;

		private ConfigEntry<bool> _repairExplicitHazardMarkers;

		private string _lastTargetedSpawnRepairKey = string.Empty;

		private ConfigEntry<bool> _modEnabled;

		private ConfigEntry<bool> _failureEnabled;

		private ConfigEntry<float> _failureChance;

		private ConfigEntry<bool> _failureScalingEnabled;

		private ConfigEntry<float> _failureIncreasePerSuccess;

		private ConfigEntry<float> _radius;

		private int _successfulDisarmsThisRound;

		private AudioClip _failureWarningBeepClip;

		private NetworkManager _registeredNetworkManager;

		private bool _networkMessageHandlersRegistered;

		private const string FailureWarningRequestMessage = "TurnOffLandmines.FailureWarningRequest.v1";

		private const string FailureWarningBroadcastMessage = "TurnOffLandmines.FailureWarningBroadcast.v1";

		private const string SuccessfulDisarmRequestMessage = "TurnOffLandmines.SuccessfulDisarmRequest.v1";

		private const string SuccessfulDisarmResultMessage = "TurnOffLandmines.SuccessfulDisarmResult.v1";

		private const string FailureWarningText = "FAILURE, RUN.";

		private const float HoldDuration = 0.45f;

		private const float ScanInterval = 0.2f;

		private const float DiscoveryInterval = 1.25f;

		private const float IdleMaintenanceInterval = 0.75f;

		private const float ExplosionDelay = 0.7f;

		private const float InteractionZoneRadius = 0.72f;

		private const float MinInteractionRadius = 0.5f;

		private const float DefaultInteractionRadius = 1f;

		private const float MaxInteractionRadius = 1.5f;

		private const float ServerDistanceTolerance = 0.15f;

		private readonly Dictionary<int, MineInteraction> _interactions = new Dictionary<int, MineInteraction>();

		private readonly HashSet<ulong> _successfulDisarmedNetworkIds = new HashSet<ulong>();

		private readonly HashSet<int> _seenMineIds = new HashSet<int>();

		private readonly List<int> _staleMineIds = new List<int>();

		private float _nextMineDiscoveryTime;

		private Landmine[] _cachedMines;

		private Coroutine _maintenanceCoroutine;

		private Sprite _vanillaInteractionIcon;

		private int _vanillaInteractionLayer = -1;

		private float _nextIconScanTime;

		private bool _roundWasActive;

		private string _lastLoggedSceneName = string.Empty;

		private string _lastDiscoverySceneName = string.Empty;

		private int _lastLoggedMineCount = -1;

		private void Awake()
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			_modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable the Turn Off Landmines interaction entirely.");
			_failureEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Failure", "Enabled", true, "Enable chance-based disarm failure. Set ChancePercent to 0 to make disarming safe.");
			_failureChance = ((BaseUnityPlugin)this).Config.Bind<float>("Failure", "ChancePercent", 15f, "Base failure chance (0-100%) before success-based scaling; the active chance is capped at 100%.");
			_failureScalingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Failure Scaling", "Enabled", true, "If enabled, each successful modded disarm this moon adds a configured number of percentage points to later failure rolls.");
			_failureIncreasePerSuccess = ((BaseUnityPlugin)this).Config.Bind<float>("Failure Scaling", "IncreasePercentPerSuccess", 10f, "Percentage points added to the failure chance after each successful modded disarm in the current moon. Ignored when scaling is disabled.");
			_radius = ((BaseUnityPlugin)this).Config.Bind<float>("Interaction", "Radius", 1f, new ConfigDescription("Maximum horizontal distance from a landmine where its disarm interaction is available (metres). Default is 1.0m; set 1.5 for the longer reach. Values are limited to 0.5–1.5m.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1.5f), Array.Empty<object>()));
			float num = Mathf.Clamp(_radius.Value, 0.5f, 1.5f);
			if (Mathf.Abs(_radius.Value - num) > 0.001f)
			{
				_radius.Value = num;
				((BaseUnityPlugin)this).Config.Save();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Failure warning beep creation deferred until a failed disarm; no custom AudioClip is created during startup.");
			_instance = this;
			_repairExplicitHazardMarkers = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawn Compatibility", "RepairExplicitHazardMarkers", true, "Only add a missing RandomMapObject component on exact MapHazardSpawnType<number> placeholders when at least one matching active-level spawn-table entry has a positive curve at the current time. Checks all duplicate matching entries. Existing marker components/lists and vanilla spawn counts are preserved.");
			InstallSpawnCompatibilityPatch();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Turn Off Landmines v1.0.0 loaded. Enabled=" + _modEnabled.Value + ", failure enabled=" + _failureEnabled.Value + ", base failure chance=" + Mathf.Clamp(_failureChance.Value, 0f, 100f) + "%, scaling=" + _failureScalingEnabled.Value + ", increase per successful disarm=" + Mathf.Max(0f, _failureIncreasePerSuccess.Value) + " percentage points, interaction radius=" + Mathf.Clamp(_radius.Value, 0.5f, 1.5f).ToString("0.##") + "m (allowed " + 0.5f.ToString("0.##") + "–" + 1.5f.ToString("0.##") + "m)."));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Multiplayer: successful disarms are requested by the interacting client, validated and applied by the host, then replicated to all clients. Host-configured radius is authoritative; default " + 1f.ToString("0.0") + "m, configurable up to " + 1.5f.ToString("0.0") + "m."));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Performance: interaction refresh runs every " + 0.2f.ToString("0.##") + "s, landmine discovery is cached for " + 1.25f.ToString("0.##") + "s, and idle/game-readiness checks run every " + 0.75f.ToString("0.##") + "s (no plugin Update polling)."));
			_maintenanceCoroutine = ((MonoBehaviour)this).StartCoroutine(MaintenanceLoop());
		}

		private void InstallSpawnCompatibilityPatch()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(RoundManager), "SpawnMapObjects", (Type[])null, (Type[])null);
				MethodInfo method = typeof(Plugin).GetMethod("RepairExplicitHazardMarkersPrefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo == null || method == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Targeted spawn compatibility patch not installed: RoundManager.SpawnMapObjects or its prefix was not found.");
					return;
				}
				_spawnCompatibilityHarmony = new Harmony("com.turnofflandmines.plugin.TargetedSpawnCompatibility");
				HarmonyMethod val = new HarmonyMethod(method);
				val.priority = 0;
				_spawnCompatibilityHarmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Targeted spawn compatibility installed. It repairs only exact MapHazardSpawnType<number> placeholders missing RandomMapObject, and only if at least one matching active-level spawn-table entry has a positive curve at the current time. It checks every duplicate matching entry; existing marker lists and vanilla counts are preserved.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not install targeted hazard-spawner compatibility: " + ex));
			}
		}

		private static void RepairExplicitHazardMarkersPrefix(RoundManager __instance)
		{
			Plugin instance = _instance;
			if ((Object)(object)instance == (Object)null || instance._repairExplicitHazardMarkers == null || !instance._repairExplicitHazardMarkers.Value)
			{
				return;
			}
			try
			{
				instance.RepairExplicitHazardMarkers(__instance, "Landmine");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)("Targeted spawn-marker repair failed for Landmine: " + ex));
			}
		}

		private void RepairExplicitHazardMarkers(RoundManager roundManager, string targetPrefabName)
		{
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)roundManager == (Object)null || (Object)(object)roundManager.currentLevel == (Object)null || roundManager.currentLevel.spawnableMapObjects == null || (Object)(object)TimeOfDay.Instance == (Object)null)
			{
				return;
			}
			GameObject val = null;
			int num = 0;
			List<string> list = new List<string>();
			float normalizedTimeOfDay = TimeOfDay.Instance.normalizedTimeOfDay;
			SpawnableMapObject[] spawnableMapObjects = roundManager.currentLevel.spawnableMapObjects;
			foreach (SpawnableMapObject val2 in spawnableMapObjects)
			{
				if (val2 == null || (Object)(object)val2.prefabToSpawn == (Object)null || !NamesMatch(((Object)val2.prefabToSpawn).name, targetPrefabName))
				{
					continue;
				}
				num++;
				if (val2.numberToSpawn == null)
				{
					list.Add("unavailable");
					continue;
				}
				float num2 = val2.numberToSpawn.Evaluate(normalizedTimeOfDay);
				list.Add(num2.ToString("0.###"));
				if (!(num2 <= 0f) && (Object)(object)val == (Object)null)
				{
					val = val2.prefabToSpawn;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				if (num > 0)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Targeted spawn repair skipped for " + targetPrefabName + ": all " + num + " matching active-level spawn-table entry/entries had no positive curve at normalized time " + normalizedTimeOfDay.ToString("0.###") + " (evaluated values: " + string.Join(", ", list.ToArray()) + "). No spawn markers or spawn rates were changed."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Targeted spawn repair skipped for " + targetPrefabName + ": the active level does not list it in spawnableMapObjects."));
				}
				return;
			}
			if (num > 1)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Targeted spawn repair found " + num + " matching " + targetPrefabName + " spawn-table entries at normalized time " + normalizedTimeOfDay.ToString("0.###") + " (evaluated values: " + string.Join(", ", list.ToArray()) + "); at least one is positive, so normal targeted-marker checks may continue."));
			}
			RandomMapObject[] array = Object.FindObjectsOfType<RandomMapObject>();
			foreach (RandomMapObject val3 in array)
			{
				if ((Object)(object)val3 == (Object)null || val3.spawnablePrefabs == null)
				{
					continue;
				}
				foreach (GameObject spawnablePrefab in val3.spawnablePrefabs)
				{
					if ((Object)(object)spawnablePrefab != (Object)null && NamesMatch(((Object)spawnablePrefab).name, targetPrefabName))
					{
						return;
					}
				}
			}
			List<GameObject> eligibleVanillaHazardPrefabs = GetEligibleVanillaHazardPrefabs(roundManager.currentLevel);
			GameObject[] array2 = Object.FindObjectsOfType<GameObject>();
			int num3 = 0;
			int num4 = 0;
			GameObject[] array3 = array2;
			foreach (GameObject val4 in array3)
			{
				if (!((Object)(object)val4 == (Object)null) && IsExplicitHazardSpawnMarker(((Object)val4).name))
				{
					num3++;
					if (!((Object)(object)val4.GetComponent<RandomMapObject>() != (Object)null))
					{
						val4.AddComponent<RandomMapObject>().spawnablePrefabs = new List<GameObject>(eligibleVanillaHazardPrefabs);
						num4++;
					}
				}
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			string name2 = ((Object)roundManager.currentLevel).name;
			if (num3 == 0)
			{
				string text = name + "|" + name2 + "|" + targetPrefabName;
				if (_lastTargetedSpawnRepairKey != text)
				{
					_lastTargetedSpawnRepairKey = text;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Targeted spawn repair found no exact MapHazardSpawnType<number> placeholder for " + targetPrefabName + " in scene '" + name + "' / level '" + name2 + "'. No other objects or spawn lists were changed."));
				}
			}
			else if (num4 == 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Targeted spawn repair found " + num3 + " explicit placeholder(s), but each already had a RandomMapObject component and no compatible spawner exists for " + targetPrefabName + ". Existing marker lists were intentionally left unchanged to preserve interior/event restrictions."));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Targeted spawn repair on level '" + name2 + "': added RandomMapObject to " + num4 + " missing component(s) on explicitly named MapHazardSpawnType<number> placeholders. Added prefab links only for hazards already in the active level's spawn table with positive vanilla spawn curves; table entries/curves/counts were not changed."));
			}
		}

		private List<GameObject> GetEligibleVanillaHazardPrefabs(SelectableLevel level)
		{
			List<GameObject> list = new List<GameObject>();
			if ((Object)(object)level == (Object)null || level.spawnableMapObjects == null || (Object)(object)TimeOfDay.Instance == (Object)null)
			{
				return list;
			}
			SpawnableMapObject[] spawnableMapObjects = level.spawnableMapObjects;
			foreach (SpawnableMapObject val in spawnableMapObjects)
			{
				if (val == null || (Object)(object)val.prefabToSpawn == (Object)null || val.numberToSpawn == null)
				{
					continue;
				}
				string name = ((Object)val.prefabToSpawn).name;
				if ((!NamesMatch(name, "Landmine") && !NamesMatch(name, "TurretContainer")) || val.numberToSpawn.Evaluate(TimeOfDay.Instance.normalizedTimeOfDay) <= 0f)
				{
					continue;
				}
				bool flag = false;
				foreach (GameObject item in list)
				{
					if ((Object)(object)item != (Object)null && NamesMatch(((Object)item).name, name))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list.Add(val.prefabToSpawn);
				}
			}
			return list;
		}

		private static bool IsExplicitHazardSpawnMarker(string objectName)
		{
			if (string.IsNullOrEmpty(objectName))
			{
				return false;
			}
			string text = objectName.Replace("(Clone)", string.Empty).Trim();
			if (!text.StartsWith("MapHazardSpawnType", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			string text2 = text.Substring("MapHazardSpawnType".Length);
			if (text2.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < text2.Length; i++)
			{
				if (text2[i] < '0' || text2[i] > '9')
				{
					return false;
				}
			}
			return true;
		}

		private static bool NamesMatch(string actual, string expected)
		{
			if (string.IsNullOrEmpty(actual) || string.IsNullOrEmpty(expected))
			{
				return false;
			}
			return string.Equals(actual.Replace("(Clone)", string.Empty).Trim(), expected, StringComparison.OrdinalIgnoreCase);
		}

		private IEnumerator MaintenanceLoop()
		{
			WaitForSecondsRealtime activeWait = new WaitForSecondsRealtime(0.2f);
			WaitForSecondsRealtime idleWait = new WaitForSecondsRealtime(0.75f);
			while (true)
			{
				EnsureNetworkMessageHandlersRegistered();
				if (!IsGameplayReady())
				{
					if (_roundWasActive || _interactions.Count > 0)
					{
						if (_roundWasActive && _successfulDisarmsThisRound > 0)
						{
							((BaseUnityPlugin)this).Logger.LogInfo((object)("Moon ended; resetting landmine failure-scaling progress after " + _successfulDisarmsThisRound + " successful modded disarm(s)."));
						}
						_successfulDisarmsThisRound = 0;
						_successfulDisarmedNetworkIds.Clear();
						ClearInteractions();
					}
					_roundWasActive = false;
					_cachedMines = null;
					_lastDiscoverySceneName = string.Empty;
					_nextMineDiscoveryTime = 0f;
					yield return idleWait;
					continue;
				}
				if (!_roundWasActive)
				{
					_roundWasActive = true;
					_successfulDisarmsThisRound = 0;
					_successfulDisarmedNetworkIds.Clear();
					_lastLoggedSceneName = string.Empty;
					_lastLoggedMineCount = -1;
					_cachedMines = null;
					_lastDiscoverySceneName = string.Empty;
					_nextMineDiscoveryTime = 0f;
				}
				if (!_modEnabled.Value)
				{
					if (_interactions.Count > 0)
					{
						ClearInteractions();
					}
					yield return idleWait;
					continue;
				}
				try
				{
					RefreshInteractions();
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Landmine interaction scan failed: " + ex));
				}
				yield return activeWait;
			}
		}

		private void EnsureNetworkMessageHandlersRegistered()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null || (_networkMessageHandlersRegistered && (Object)(object)_registeredNetworkManager == (Object)(object)singleton))
			{
				return;
			}
			UnregisterNetworkMessageHandlers();
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			bool flag4 = false;
			try
			{
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffLandmines.FailureWarningRequest.v1", new HandleNamedMessageDelegate(HandleFailureWarningRequest));
				flag = true;
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffLandmines.FailureWarningBroadcast.v1", new HandleNamedMessageDelegate(HandleFailureWarningBroadcast));
				flag2 = true;
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffLandmines.SuccessfulDisarmRequest.v1", new HandleNamedMessageDelegate(HandleSuccessfulDisarmRequest));
				flag3 = true;
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffLandmines.SuccessfulDisarmResult.v1", new HandleNamedMessageDelegate(HandleSuccessfulDisarmResult));
				flag4 = true;
				_registeredNetworkManager = singleton;
				_networkMessageHandlersRegistered = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Networked landmine warning and successful-disarm messaging registered.");
			}
			catch (Exception ex)
			{
				try
				{
					if (flag4)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.SuccessfulDisarmResult.v1");
					}
					if (flag3)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.SuccessfulDisarmRequest.v1");
					}
					if (flag2)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.FailureWarningBroadcast.v1");
					}
					if (flag)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.FailureWarningRequest.v1");
					}
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Could not clean up partial landmine network handler registration: " + ex2.Message));
				}
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not register landmine network messaging; partial handlers were rolled back: " + ex));
				_registeredNetworkManager = null;
				_networkMessageHandlersRegistered = false;
			}
		}

		private void UnregisterNetworkMessageHandlers()
		{
			if (!_networkMessageHandlersRegistered || (Object)(object)_registeredNetworkManager == (Object)null)
			{
				_registeredNetworkManager = null;
				_networkMessageHandlersRegistered = false;
				return;
			}
			try
			{
				if (_registeredNetworkManager.CustomMessagingManager != null)
				{
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.FailureWarningRequest.v1");
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.FailureWarningBroadcast.v1");
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.SuccessfulDisarmRequest.v1");
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffLandmines.SuccessfulDisarmResult.v1");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Could not unregister landmine network messages during teardown: " + ex.Message));
			}
			_registeredNetworkManager = null;
			_networkMessageHandlersRegistered = false;
		}

		private unsafe void SendFailureWarningRequest(Landmine mine)
		{
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			EnsureNetworkMessageHandlersRegistered();
			NetworkManager singleton = NetworkManager.Singleton;
			NetworkObject val = (((Object)(object)mine != (Object)null) ? ((Component)mine).GetComponent<NetworkObject>() : null);
			if ((Object)(object)val == (Object)null && (Object)(object)mine != (Object)null)
			{
				val = ((Component)mine).GetComponentInParent<NetworkObject>();
			}
			if ((Object)(object)val == (Object)null && (Object)(object)mine != (Object)null)
			{
				val = ((Component)mine).GetComponentInChildren<NetworkObject>(true);
			}
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null || (Object)(object)val == (Object)null || !val.IsSpawned)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not network the landmine failure beep because the mine's spawned NetworkObject was unavailable. The local warning beep still played.");
				return;
			}
			ulong networkObjectId = val.NetworkObjectId;
			try
			{
				if (singleton.IsServer)
				{
					SendFailureWarningBroadcastToClients(singleton, networkObjectId, null);
					return;
				}
				if (!_networkMessageHandlersRegistered || (Object)(object)_registeredNetworkManager != (Object)(object)singleton)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Network warning handlers are not ready; this failed disarm's beep will be local only.");
					return;
				}
				FastBufferWriter val2 = default(FastBufferWriter);
				((FastBufferWriter)(ref val2))..ctor(8, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
					singleton.CustomMessagingManager.SendNamedMessage("TurnOffLandmines.FailureWarningRequest.v1", 0uL, val2, (NetworkDelivery)3);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not send the networked landmine failure warning; the local beep still played: " + ex.Message));
			}
		}

		private void HandleFailureWarningRequest(ulong senderClientId, FastBufferReader reader)
		{
			//IL_001f: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsServer)
			{
				ulong networkObjectId = default(ulong);
				try
				{
					((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed landmine warning request from client " + senderClientId + ": " + ex.Message));
					return;
				}
				if (singleton.ConnectedClients == null || !singleton.ConnectedClients.ContainsKey(senderClientId))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored landmine warning request from unconnected client " + senderClientId + "."));
					return;
				}
				if (!TryGetSpawnedMine(singleton, networkObjectId, out var mine))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored landmine warning request because NetworkObject " + networkObjectId + " did not resolve to a spawned Landmine."));
					return;
				}
				PlayFailureWarningForMine(mine);
				SendFailureWarningBroadcastToClients(singleton, networkObjectId, senderClientId);
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Relayed landmine failure beep for NetworkObject " + networkObjectId + " from client " + senderClientId + "."));
			}
		}

		private void HandleFailureWarningBroadcast(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0022: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && !singleton.IsServer && senderClientId == 0L)
			{
				ulong networkObjectId = default(ulong);
				try
				{
					((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed relayed landmine warning: " + ex.Message));
					return;
				}
				if (TryGetSpawnedMine(singleton, networkObjectId, out var mine))
				{
					PlayFailureWarningForMine(mine);
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Played relayed landmine failure beep for NetworkObject " + networkObjectId + "."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not play relayed landmine warning because NetworkObject " + networkObjectId + " was not found on this client."));
				}
			}
		}

		private unsafe void SendFailureWarningBroadcastToClients(NetworkManager manager, ulong networkObjectId, ulong? excludedClientId)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)manager == (Object)null || !manager.IsServer || manager.CustomMessagingManager == null)
			{
				return;
			}
			List<ulong> list = new List<ulong>();
			try
			{
				foreach (ulong connectedClientsId in manager.ConnectedClientsIds)
				{
					if (connectedClientsId != manager.LocalClientId && (!excludedClientId.HasValue || connectedClientsId != excludedClientId.Value))
					{
						list.Add(connectedClientsId);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not snapshot clients for landmine warning relay: " + ex.Message));
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			foreach (ulong item in list)
			{
				try
				{
					((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
					try
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
						manager.CustomMessagingManager.SendNamedMessage("TurnOffLandmines.FailureWarningBroadcast.v1", item, val, (NetworkDelivery)3);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
					}
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not relay landmine warning for NetworkObject " + networkObjectId + " to client " + item + ": " + ex2.Message));
				}
			}
		}

		private static bool TryGetSpawnedMine(NetworkManager manager, ulong networkObjectId, out Landmine mine)
		{
			mine = null;
			if ((Object)(object)manager == (Object)null || manager.SpawnManager == null || manager.SpawnManager.SpawnedObjects == null)
			{
				return false;
			}
			if (!manager.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out var value) || (Object)(object)value == (Object)null || !value.IsSpawned)
			{
				return false;
			}
			mine = ((Component)value).GetComponent<Landmine>();
			if ((Object)(object)mine == (Object)null)
			{
				mine = ((Component)value).GetComponentInChildren<Landmine>(true);
			}
			return (Object)(object)mine != (Object)null;
		}

		private void PlayFailureWarningForMine(Landmine mine)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return;
			}
			foreach (MineInteraction value in _interactions.Values)
			{
				if (value != null && (Object)(object)value.Mine == (Object)(object)mine)
				{
					if (!((Object)(object)value.WarningAudioSource != (Object)null) || !value.WarningAudioSource.isPlaying)
					{
						StartFailureWarningBeep(value);
					}
					return;
				}
			}
			MineInteraction state = new MineInteraction
			{
				Mine = mine
			};
			StartFailureWarningBeep(state);
		}

		private unsafe void RequestSuccessfulDisarm(MineInteraction state)
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			Landmine val = state?.Mine;
			if ((Object)(object)val == (Object)null)
			{
				ResetDisarmProcessing(val);
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null)
			{
				ApplySuccessfulDisarmLocally(val);
				((BaseUnityPlugin)this).Logger.LogWarning((object)"No active Netcode session was available; applied the successful disarm locally.");
				return;
			}
			NetworkObject mineNetworkObject = GetMineNetworkObject(val);
			if ((Object)(object)mineNetworkObject == (Object)null || !mineNetworkObject.IsSpawned)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not synchronize a successful disarm because the landmine's spawned NetworkObject was unavailable; the interaction was cancelled instead of changing only this client.");
				ResetDisarmProcessing(val);
				return;
			}
			EnsureNetworkMessageHandlersRegistered();
			ulong networkObjectId = mineNetworkObject.NetworkObjectId;
			if (singleton.IsServer)
			{
				ProcessSuccessfulDisarmRequest(singleton.LocalClientId, networkObjectId);
				return;
			}
			if (!_networkMessageHandlersRegistered || (Object)(object)_registeredNetworkManager != (Object)(object)singleton)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Successful disarm cancelled because the network message handlers were not ready; retry the interaction.");
				ResetDisarmProcessing(val);
				return;
			}
			try
			{
				FastBufferWriter val2 = default(FastBufferWriter);
				((FastBufferWriter)(ref val2))..ctor(8, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
					singleton.CustomMessagingManager.SendNamedMessage("TurnOffLandmines.SuccessfulDisarmRequest.v1", 0uL, val2, (NetworkDelivery)3);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose();
				}
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Requested host-authoritative successful disarm for Landmine NetworkObject " + networkObjectId + "."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not send the successful-disarm request; interaction cancelled: " + ex.Message));
				ResetDisarmProcessing(val);
			}
		}

		private void HandleSuccessfulDisarmRequest(ulong senderClientId, FastBufferReader reader)
		{
			//IL_001f: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsServer)
			{
				ulong networkObjectId = default(ulong);
				try
				{
					((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed successful-disarm request from client " + senderClientId + ": " + ex.Message));
					return;
				}
				ProcessSuccessfulDisarmRequest(senderClientId, networkObjectId);
			}
		}

		private void ProcessSuccessfulDisarmRequest(ulong senderClientId, ulong networkObjectId)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null)
			{
				return;
			}
			if (senderClientId != singleton.LocalClientId && (singleton.ConnectedClients == null || !singleton.ConnectedClients.ContainsKey(senderClientId)))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected successful-disarm request from unconnected client " + senderClientId + "."));
				return;
			}
			if (!IsGameplayReady() || !TryGetSpawnedMine(singleton, networkObjectId, out var mine) || (Object)(object)mine == (Object)null || !((Behaviour)mine).isActiveAndEnabled || IsMineSpent(mine))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected successful-disarm request for invalid, inactive, or already-spent Landmine NetworkObject " + networkObjectId + "."));
				SendSuccessfulDisarmResult(singleton, senderClientId, networkObjectId, accepted: false);
				return;
			}
			PlayerControllerB val = FindPlayerForClientId(singleton, senderClientId);
			if ((Object)(object)val == (Object)null || val.isPlayerDead || !val.isPlayerControlled)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected successful-disarm request for NetworkObject " + networkObjectId + " because the requesting player was not alive/controlled."));
				SendSuccessfulDisarmResult(singleton, senderClientId, networkObjectId, accepted: false);
				return;
			}
			Vector3 val2 = ((Component)val).transform.position - ((Component)mine).transform.position;
			val2.y = 0f;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			float num = Mathf.Clamp(_radius.Value, 0.5f, 1.5f);
			if (magnitude > num + 0.15f)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected successful-disarm request for NetworkObject " + networkObjectId + ": player was " + magnitude.ToString("0.00") + "m away, beyond the host's configured " + num.ToString("0.00") + "m radius (plus " + 0.15f.ToString("0.00") + "m network tolerance)."));
				SendSuccessfulDisarmResult(singleton, senderClientId, networkObjectId, accepted: false);
			}
			else if (!ApplySuccessfulDisarmLocally(mine))
			{
				SendSuccessfulDisarmResult(singleton, senderClientId, networkObjectId, accepted: false);
			}
			else
			{
				SendSuccessfulDisarmResult(singleton, senderClientId, networkObjectId, accepted: true);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Host accepted and replicated successful landmine disarm for NetworkObject " + networkObjectId + " from client " + senderClientId + ". Distance=" + magnitude.ToString("0.00") + "m; host radius=" + num.ToString("0.00") + "m."));
			}
		}

		private void HandleSuccessfulDisarmResult(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0022: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && !singleton.IsServer && senderClientId == 0L)
			{
				ulong networkObjectId = default(ulong);
				bool flag = default(bool);
				try
				{
					((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
					((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed successful-disarm result: " + ex.Message));
					return;
				}
				if (!TryGetSpawnedMine(singleton, networkObjectId, out var mine))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not apply successful-disarm result because Landmine NetworkObject " + networkObjectId + " was not found on this client."));
				}
				else if (flag)
				{
					ApplySuccessfulDisarmLocally(mine);
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Applied host-replicated successful disarm for Landmine NetworkObject " + networkObjectId + "."));
				}
				else
				{
					ResetDisarmProcessing(mine);
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Host rejected successful disarm for Landmine NetworkObject " + networkObjectId + "; the interaction has been released."));
				}
			}
		}

		private unsafe void SendSuccessfulDisarmResult(NetworkManager manager, ulong requestingClientId, ulong networkObjectId, bool accepted)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)manager == (Object)null || !manager.IsServer || manager.CustomMessagingManager == null)
			{
				return;
			}
			List<ulong> list = new List<ulong>();
			try
			{
				if (accepted)
				{
					foreach (ulong connectedClientsId in manager.ConnectedClientsIds)
					{
						if (connectedClientsId != manager.LocalClientId)
						{
							list.Add(connectedClientsId);
						}
					}
				}
				else if (requestingClientId != manager.LocalClientId && manager.ConnectedClients != null && manager.ConnectedClients.ContainsKey(requestingClientId))
				{
					list.Add(requestingClientId);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not build recipient list for landmine disarm result: " + ex.Message));
				return;
			}
			if (!accepted && requestingClientId == manager.LocalClientId)
			{
				if (TryGetSpawnedMine(manager, networkObjectId, out var mine))
				{
					ResetDisarmProcessing(mine);
				}
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			foreach (ulong item in list)
			{
				try
				{
					((FastBufferWriter)(ref val))..ctor(9, (Allocator)2, -1);
					try
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
						((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref accepted, default(ForPrimitives));
						manager.CustomMessagingManager.SendNamedMessage("TurnOffLandmines.SuccessfulDisarmResult.v1", item, val, (NetworkDelivery)3);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
					}
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not send landmine disarm result for NetworkObject " + networkObjectId + " to client " + item + ": " + ex2.Message));
				}
			}
		}

		private bool ApplySuccessfulDisarmLocally(Landmine mine)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return false;
			}
			ulong mineNetworkObjectId = GetMineNetworkObjectId(mine);
			if (mineNetworkObjectId != 0L && !_successfulDisarmedNetworkIds.Add(mineNetworkObjectId))
			{
				DisableInteractionForMine(mine);
				return true;
			}
			if (!IsMineSpent(mine))
			{
				DisarmMine(mine);
			}
			DisableInteractionForMine(mine);
			_successfulDisarmsThisRound++;
			float num = Mathf.Clamp(Mathf.Clamp(_failureChance.Value, 0f, 100f) + (_failureScalingEnabled.Value ? (Mathf.Max(0f, _failureIncreasePerSuccess.Value) * (float)_successfulDisarmsThisRound) : 0f), 0f, 100f);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Landmine disarmed successfully on this peer. Successful modded disarms this moon=" + _successfulDisarmsThisRound + "; next failure chance=" + num.ToString("0.##") + "%. NetworkObject=" + mineNetworkObjectId + "."));
			return true;
		}

		private void DisableInteractionForMine(Landmine mine)
		{
			foreach (MineInteraction value in _interactions.Values)
			{
				if (value != null && !((Object)(object)value.Mine != (Object)(object)mine))
				{
					value.Processing = false;
					if ((Object)(object)value.Trigger != (Object)null)
					{
						value.Trigger.interactable = false;
					}
					if ((Object)(object)value.Zone != (Object)null)
					{
						value.Zone.SetActive(false);
					}
				}
			}
		}

		private void ResetDisarmProcessing(Landmine mine)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return;
			}
			foreach (MineInteraction value in _interactions.Values)
			{
				if (value != null && !((Object)(object)value.Mine != (Object)(object)mine))
				{
					value.Processing = false;
					if ((Object)(object)value.Trigger != (Object)null)
					{
						value.Trigger.interactable = false;
					}
				}
			}
		}

		private static ulong GetMineNetworkObjectId(Landmine mine)
		{
			NetworkObject mineNetworkObject = GetMineNetworkObject(mine);
			if (!((Object)(object)mineNetworkObject != (Object)null) || !mineNetworkObject.IsSpawned)
			{
				return 0uL;
			}
			return mineNetworkObject.NetworkObjectId;
		}

		private static NetworkObject GetMineNetworkObject(Landmine mine)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return null;
			}
			NetworkObject val = ((Component)mine).GetComponent<NetworkObject>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)mine).GetComponentInParent<NetworkObject>();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)mine).GetComponentInChildren<NetworkObject>(true);
			}
			return val;
		}

		private static PlayerControllerB FindPlayerForClientId(NetworkManager manager, ulong clientId)
		{
			try
			{
				if ((Object)(object)manager != (Object)null && manager.ConnectedClients != null && manager.ConnectedClients.TryGetValue(clientId, out var value) && value != null && (Object)(object)value.PlayerObject != (Object)null)
				{
					PlayerControllerB val = ((Component)value.PlayerObject).GetComponent<PlayerControllerB>();
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)value.PlayerObject).GetComponentInChildren<PlayerControllerB>(true);
					}
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
				Type type = Type.GetType("StartOfRound, Assembly-CSharp");
				if (GetMember((type != null) ? GetStaticMember(type, "Instance") : null, "allPlayerScripts") is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						PlayerControllerB val2 = (PlayerControllerB)((item is PlayerControllerB) ? item : null);
						if (!((Object)(object)val2 == (Object)null))
						{
							object member = GetMember(val2, "playerClientId");
							if (member is ulong && (ulong)member == clientId)
							{
								return val2;
							}
							if (member is int && (ulong)(int)member == clientId)
							{
								return val2;
							}
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static bool IsGameplayReady()
		{
			try
			{
				Type type = Type.GetType("StartOfRound, Assembly-CSharp");
				object obj = ((type != null) ? GetStaticMember(type, "Instance") : null);
				if (obj == null)
				{
					return false;
				}
				object member = GetMember(obj, "shipHasLanded");
				if (!(member is bool) || !(bool)member)
				{
					return false;
				}
				object member2 = GetMember(obj, "inShipPhase");
				if (member2 is bool && (bool)member2)
				{
					return false;
				}
				Type type2 = Type.GetType("RoundManager, Assembly-CSharp");
				object obj2 = ((type2 != null) ? GetStaticMember(type2, "Instance") : null);
				return obj2 != null && GetMember(obj2, "currentLevel") != null;
			}
			catch
			{
				return false;
			}
		}

		private void RefreshInteractions()
		{
			//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)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			RefreshVanillaInteractionIconIfNeeded();
			string turnOffPrompt = GetTurnOffPrompt();
			if (!_modEnabled.Value)
			{
				ClearInteractions();
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (_cachedMines == null || name != _lastDiscoverySceneName || Time.unscaledTime >= _nextMineDiscoveryTime)
			{
				_cachedMines = Object.FindObjectsOfType<Landmine>();
				_lastDiscoverySceneName = name;
				_nextMineDiscoveryTime = Time.unscaledTime + 1.25f;
			}
			Landmine[] array = _cachedMines ?? Array.Empty<Landmine>();
			Landmine[] array2;
			if (name != _lastLoggedSceneName || array.Length != _lastLoggedMineCount)
			{
				_lastLoggedSceneName = name;
				_lastLoggedMineCount = array.Length;
				RoundManager instance = RoundManager.Instance;
				string text = (((Object)(object)instance != (Object)null && (Object)(object)instance.currentLevel != (Object)null) ? ((Object)instance.currentLevel).name : "<unknown>");
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Spawn-safe scan in scene '" + name + "' on level '" + text + "': found " + array.Length + " active Landmine component(s). This mod does not register or spawn landmine prefabs."));
				array2 = array;
				foreach (Landmine val in array2)
				{
					if ((Object)(object)val != (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Detected active Landmine instance " + ((Object)val).GetInstanceID() + " at world position " + ((object)((Component)val).transform.position/*cast due to .constrained prefix*/).ToString() + "."));
					}
				}
			}
			_seenMineIds.Clear();
			PlayerControllerB localPlayer = GetLocalPlayer();
			array2 = array;
			foreach (Landmine val2 in array2)
			{
				if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).isActiveAndEnabled)
				{
					continue;
				}
				int instanceID = ((Object)val2).GetInstanceID();
				_seenMineIds.Add(instanceID);
				if (IsMineSpent(val2))
				{
					if (_interactions.TryGetValue(instanceID, out var value) && value != null && (Object)(object)value.Zone != (Object)null)
					{
						if ((Object)(object)value.Trigger != (Object)null)
						{
							value.Trigger.interactable = false;
						}
						value.Zone.SetActive(false);
					}
					continue;
				}
				if (!_interactions.TryGetValue(instanceID, out var value2) || (Object)(object)value2.Mine == (Object)null)
				{
					value2 = CreateInteraction(val2);
					_interactions[instanceID] = value2;
				}
				if (value2 != null && !((Object)(object)value2.Zone == (Object)null) && !((Object)(object)value2.Trigger == (Object)null))
				{
					Vector3 val3 = (((Object)(object)localPlayer != (Object)null) ? (((Component)localPlayer).transform.position - ((Component)val2).transform.position) : (Vector3.one * 999f));
					val3.y = 0f;
					float num = Mathf.Clamp(_radius.Value, 0.5f, 1.5f);
					bool flag = (Object)(object)localPlayer != (Object)null && ((Vector3)(ref val3)).magnitude <= num && !value2.Processing && !IsMineSpent(val2);
					value2.Trigger.interactable = flag;
					value2.Zone.transform.position = ((Component)val2).transform.position + Vector3.up * 0.45f;
					if ((Object)(object)value2.Trigger.hoverIcon == (Object)null && (Object)(object)_vanillaInteractionIcon != (Object)null)
					{
						value2.Trigger.hoverIcon = _vanillaInteractionIcon;
					}
					if (value2.Zone.activeSelf != flag)
					{
						value2.Zone.SetActive(flag);
					}
					string text2 = (value2.Processing ? "FAILURE, RUN." : turnOffPrompt);
					if (value2.Trigger.hoverTip != text2)
					{
						value2.Trigger.hoverTip = text2;
					}
					value2.Trigger.holdTip = (value2.Processing ? "FAILURE, RUN." : "Turning off...");
				}
			}
			_staleMineIds.Clear();
			foreach (KeyValuePair<int, MineInteraction> interaction in _interactions)
			{
				if (!_seenMineIds.Contains(interaction.Key) || interaction.Value == null || (Object)(object)interaction.Value.Mine == (Object)null)
				{
					_staleMineIds.Add(interaction.Key);
				}
			}
			foreach (int staleMineId in _staleMineIds)
			{
				StopFailureWarningBeep(_interactions[staleMineId]);
				if (_interactions[staleMineId] != null && (Object)(object)_interactions[staleMineId].Zone != (Object)null)
				{
					Object.Destroy((Object)(object)_interactions[staleMineId].Zone);
				}
				_interactions.Remove(staleMineId);
			}
		}

		private MineInteraction CreateInteraction(Landmine mine)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			GameObject val = new GameObject("TurnOffLandmines_Interaction");
			EnsureNativeInteractionObject(val);
			val.SetActive(false);
			SphereCollider val2 = val.AddComponent<SphereCollider>();
			((Collider)val2).isTrigger = true;
			val2.radius = 0.72f;
			EnsureNativeInteractionObject(val);
			InteractTrigger val3 = val.AddComponent<InteractTrigger>();
			val3.hoverTip = GetTurnOffPrompt();
			val3.holdTip = "Turning off...";
			val3.disabledHoverTip = string.Empty;
			val3.animationString = string.Empty;
			val3.interactable = false;
			val3.hoverIcon = _vanillaInteractionIcon;
			val3.oneHandedItemAllowed = true;
			val3.twoHandedItemAllowed = true;
			val3.holdInteraction = true;
			val3.timeToHold = 0.45f;
			val3.timeToHoldSpeedMultiplier = 1f;
			val3.interactCooldown = true;
			val3.cooldownTime = 0.5f;
			val3.triggerOnce = false;
			val3.stopAnimationString = "SA_stopAnimation";
			val3.animationWaitTime = 2f;
			val3.lockPlayerPosition = false;
			val3.disableTriggerMesh = true;
			val3.holdingInteractEvent = new InteractEventFloat();
			val3.onInteract = new InteractEvent();
			val3.onInteractEarly = new InteractEvent();
			val3.onStopInteract = new InteractEvent();
			val3.onCancelAnimation = new InteractEvent();
			MineInteraction state = new MineInteraction
			{
				Mine = mine,
				Zone = val,
				Collider = val2,
				Trigger = val3
			};
			((UnityEvent<PlayerControllerB>)(object)val3.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate(PlayerControllerB player)
			{
				TryTurnOff(state, player);
			});
			return state;
		}

		private AudioClip CreateFailureWarningBeepClip()
		{
			int num = Mathf.CeilToInt(30870f);
			float[] array = new float[num];
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)i / 44100f;
				float num3 = num2 % 0.1f;
				if (!(num3 >= 0.055f))
				{
					float num4 = Mathf.Clamp01(Mathf.Min(num3 / 0.003f, (0.055f - num3) / 0.003f));
					array[i] = Mathf.Sin(MathF.PI * 3100f * num2) * 0.32f * num4;
				}
			}
			AudioClip val = AudioClip.Create("TurnOffLandmines_FailureWarningBeep", num, 1, 44100, false);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			val.SetData(array, 0);
			return val;
		}

		private void StartFailureWarningBeep(MineInteraction state)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (state == null || (Object)(object)state.Mine == (Object)null)
			{
				return;
			}
			if ((Object)(object)_failureWarningBeepClip == (Object)null)
			{
				try
				{
					_failureWarningBeepClip = CreateFailureWarningBeepClip();
					if ((Object)(object)_failureWarningBeepClip == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not create the landmine failure warning beep; text warning and explosion path will still run.");
						return;
					}
					((BaseUnityPlugin)this).Logger.LogDebug((object)"Created the landmine failure warning beep lazily after a failed disarm.");
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not create the landmine failure warning beep; text warning and explosion path will still run: " + ex.Message));
					return;
				}
			}
			try
			{
				StopFailureWarningBeep(state);
				GameObject val = new GameObject("TurnOffLandmines_FailureWarningAudio");
				val.transform.SetParent(((Component)state.Mine).transform, false);
				val.transform.localPosition = Vector3.up * 0.35f;
				AudioSource val2 = val.AddComponent<AudioSource>();
				val2.playOnAwake = false;
				val2.loop = false;
				val2.clip = _failureWarningBeepClip;
				val2.volume = 0.85f;
				val2.pitch = 1f;
				val2.spatialBlend = 1f;
				val2.dopplerLevel = 0f;
				val2.rolloffMode = (AudioRolloffMode)0;
				val2.minDistance = 1f;
				val2.maxDistance = 20f;
				state.WarningAudioObject = val;
				state.WarningAudioSource = val2;
				val2.Play();
				Object.Destroy((Object)(object)val, _failureWarningBeepClip.length + 0.1f);
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not start the landmine failure warning beep: " + ex2.Message));
			}
		}

		private void StopFailureWarningBeep(MineInteraction state)
		{
			if (state != null)
			{
				if ((Object)(object)state.WarningAudioSource != (Object)null)
				{
					state.WarningAudioSource.Stop();
				}
				if ((Object)(object)state.WarningAudioObject != (Object)null)
				{
					Object.Destroy((Object)(object)state.WarningAudioObject);
				}
				state.WarningAudioSource = null;
				state.WarningAudioObject = null;
			}
		}

		private void TryTurnOff(MineInteraction state, PlayerControllerB player)
		{
			if (!_modEnabled.Value || state == null || (Object)(object)state.Mine == (Object)null || state.Processing || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)GetLocalPlayer() || IsMineSpent(state.Mine))
			{
				return;
			}
			state.Processing = true;
			state.Trigger.interactable = false;
			float num = Mathf.Clamp(_failureChance.Value, 0f, 100f);
			float num2 = num;
			if (_failureScalingEnabled.Value)
			{
				float num3 = Mathf.Max(0f, _failureIncreasePerSuccess.Value);
				num2 = Mathf.Clamp(num + num3 * (float)_successfulDisarmsThisRound, 0f, 100f);
			}
			((BaseUnityPlugin)this).Logger.LogDebug((object)("Landmine disarm roll: active failure chance=" + num2.ToString("0.##") + "%, base=" + num.ToString("0.##") + "%, successful modded disarms this moon=" + _successfulDisarmsThisRound + ", scaling=" + _failureScalingEnabled.Value + "."));
			if (_failureEnabled.Value && num2 > 0f && Random.Range(0f, 100f) < num2)
			{
				state.Trigger.hoverTip = "FAILURE, RUN.";
				state.Trigger.holdTip = "FAILURE, RUN.";
				HUDManager instance = HUDManager.Instance;
				if (instance != null)
				{
					instance.DisplayTip("FAILURE, RUN.", string.Empty, true, false, "LC_Tip1");
				}
				StartFailureWarningBeep(state);
				SendFailureWarningRequest(state.Mine);
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Landmine turn-off attempt failed; local warning started, network relay requested, and explosion scheduled in " + 0.7f.ToString("0.0") + " seconds."));
				((MonoBehaviour)this).StartCoroutine(ExplodeAfterDelay(state, 0.7f));
			}
			else
			{
				RequestSuccessfulDisarm(state);
			}
		}

		private IEnumerator ExplodeAfterDelay(MineInteraction state, float delay)
		{
			yield return (object)new WaitForSecondsRealtime(delay);
			if (state == null || (Object)(object)state.Mine == (Object)null)
			{
				StopFailureWarningBeep(state);
				yield break;
			}
			try
			{
				Landmine mine = state.Mine;
				bool flag = false;
				if (HasZeroArgumentMethod(mine, "ExplodeMineServerRpc"))
				{
					InvokeMineMethod(mine, "SetOffMineAnimation");
					SetMember(mine, "sendingExplosionRPC", true);
					flag = InvokeMineMethod(mine, "ExplodeMineServerRpc");
				}
				if (!flag)
				{
					flag = InvokeMineMethod(mine, "ExplodeMine");
				}
				if (!flag)
				{
					flag = InvokeMineMethod(mine, "TriggerMineOnLocalClientByExiting");
				}
				if (flag)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Invoked the landmine failure explosion path after " + delay.ToString("0.0") + " seconds. Instance=" + ((Object)mine).GetInstanceID() + "."));
				}
				if (!flag)
				{
					bool flag2 = InvokeMineMethod(mine, "SetOffMineAnimation");
					((BaseUnityPlugin)this).Logger.LogError((object)(flag2 ? "Only the mine animation method was available; a server explosion method could not be called. The explosion could not be confirmed." : "Could not find a supported mine explosion method. The failure warning was shown, but the explosion could not be triggered."));
				}
				if ((Object)(object)state.Zone != (Object)null)
				{
					state.Zone.SetActive(false);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to trigger landmine explosion after disarm failure: " + ex));
			}
			finally
			{
				StopFailureWarningBeep(state);
				if (state != null && (Object)(object)state.Zone != (Object)null)
				{
					state.Zone.SetActive(false);
				}
			}
		}

		private void DisarmMine(Landmine mine)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return;
			}
			object member = GetMember(mine, "mineAnimator");
			Animator val = (Animator)((member is Animator) ? member : null);
			if ((Object)(object)val != (Object)null)
			{
				((Behaviour)val).enabled = false;
			}
			SetMember(mine, "hasExploded", true);
			bool num = InvokeMineMethod(mine, "ToggleMine", argument: false);
			SetMember(mine, "mineActivated", false);
			if (num)
			{
				return;
			}
			Collider[] componentsInChildren = ((Component)mine).GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
			((BaseUnityPlugin)this).Logger.LogWarning((object)"ToggleMine(false) was unavailable; used the local safety fallback for this landmine.");
		}

		private static bool HasZeroArgumentMethod(Landmine mine, string name)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return false;
			}
			return ((object)mine).GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) != null;
		}

		private static bool InvokeMineMethod(Landmine mine, string name)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return false;
			}
			MethodInfo method = ((object)mine).GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method == null)
			{
				return false;
			}
			try
			{
				method.Invoke(mine, null);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool InvokeMineMethod(Landmine mine, string name, bool argument)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return false;
			}
			MethodInfo method = ((object)mine).GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null);
			if (method == null)
			{
				return false;
			}
			try
			{
				method.Invoke(mine, new object[1] { argument });
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsMineSpent(Landmine mine)
		{
			if ((Object)(object)mine == (Object)null)
			{
				return true;
			}
			object member = GetMember(mine, "hasExploded");
			if (member is bool)
			{
				return (bool)member;
			}
			return false;
		}

		private static PlayerControllerB GetLocalPlayer()
		{
			GameNetworkManager instance = GameNetworkManager.Instance;
			PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null);
			if (!((Object)(object)val != (Object)null) || !val.isPlayerControlled || val.isPlayerDead || val.isTypingChat || val.inTerminalMenu)
			{
				return null;
			}
			return val;
		}

		private static object GetMember(object instance, string name)
		{
			if (instance == null)
			{
				return null;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = instance.GetType().GetField(name, bindingAttr);
			if (field != null)
			{
				return field.GetValue(instance);
			}
			PropertyInfo property = instance.GetType().GetProperty(name, bindingAttr);
			if (!(property != null))
			{
				return null;
			}
			return property.GetValue(instance, null);
		}

		private static void SetMember(object instance, string name, object value)
		{
			if (instance == null)
			{
				return;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = instance.GetType().GetField(name, bindingAttr);
			if (field != null && (value == null || field.FieldType.IsInstanceOfType(value)))
			{
				try
				{
					field.SetValue(instance, value);
					return;
				}
				catch
				{
					return;
				}
			}
			PropertyInfo property = instance.GetType().GetProperty(name, bindingAttr);
			if (!(property != null) || !property.CanWrite || (value != null && !property.PropertyType.IsInstanceOfType(value)))
			{
				return;
			}
			try
			{
				property.SetValue(instance, value, null);
			}
			catch
			{
			}
		}

		private string GetTurnOffPrompt()
		{
			string text = GetInteractBindingDisplayName();
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "E";
			}
			text = text.Trim().Trim('[', ']');
			return "Turn off : [" + text + "]";
		}

		private string GetInteractBindingDisplayName()
		{
			//IL_0169: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type type = Type.GetType("IngamePlayerSettings, Assembly-CSharp");
				if (type == null)
				{
					return "E";
				}
				object staticMember = GetStaticMember(type, "Instance");
				if (staticMember == null)
				{
					return "E";
				}
				object member = GetMember(GetMember(staticMember, "playerInput"), "actions");
				InputActionAsset val = (InputActionAsset)((member is InputActionAsset) ? member : null);
				if ((Object)(object)val == (Object)null)
				{
					return "E";
				}
				InputAction val2 = val.FindAction("Interact", false);
				if (val2 == null)
				{
					val2 = val.FindAction("Movement/Interact", false);
				}
				if (val2 == null)
				{
					return "E";
				}
				int num = -1;
				if (val2.activeControl != null)
				{
					num = InputActionRebindingExtensions.GetBindingIndexForControl(val2, val2.activeControl);
				}
				if (num < 0)
				{
					bool flag = Gamepad.current != null && (Keyboard.current == null || ((InputDevice)Gamepad.current).lastUpdateTime > ((InputDevice)Keyboard.current).lastUpdateTime);
					for (int i = 0; i < val2.bindings.Count; i++)
					{
						InputBinding val3 = val2.bindings[i];
						object obj = ((InputBinding)(ref val3)).effectivePath;
						if (obj == null)
						{
							val3 = val2.bindings[i];
							obj = ((InputBinding)(ref val3)).path ?? string.Empty;
						}
						string text = (string)obj;
						if (flag && text.IndexOf("<Gamepad>/", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							num = i;
							break;
						}
						if (!flag && text.IndexOf("<Keyboard>/", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							num = i;
							break;
						}
					}
				}
				string text2 = ((num >= 0) ? InputActionRebindingExtensions.GetBindingDisplayString(val2, num, (DisplayStringOptions)0) : InputActionRebindingExtensions.GetBindingDisplayString(val2, (DisplayStringOptions)0, (string)null));
				return string.IsNullOrWhiteSpace(text2) ? "E" : text2;
			}
			catch
			{
				return "E";
			}
		}

		private static object GetStaticMember(Type type, string name)
		{
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = type.GetField(name, bindingAttr);
			if (field != null)
			{
				return field.GetValue(null);
			}
			PropertyInfo property = type.GetProperty(name, bindingAttr);
			if (!(property != null))
			{
				return null;
			}
			return property.GetValue(null, null);
		}

		private void RefreshVanillaInteractionIconIfNeeded()
		{
			if ((Object)(object)_vanillaInteractionIcon != (Object)null || Time.unscaledTime < _nextIconScanTime)
			{
				return;
			}
			_nextIconScanTime = Time.unscaledTime + 1f;
			InteractTrigger[] array = Object.FindObjectsOfType<InteractTrigger>();
			InteractTrigger[] array2 = array;
			foreach (InteractTrigger val in array2)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.hoverIcon == (Object)null) && !(((Object)((Component)val).gameObject).name == "TurnOffLandmines_Interaction"))
				{
					string text = val.hoverTip ?? string.Empty;
					if (text.IndexOf("open", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("door", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						ApplyVanillaInteractionStyle(val);
						break;
					}
				}
			}
			if (!((Object)(object)_vanillaInteractionIcon == (Object)null))
			{
				return;
			}
			array2 = array;
			foreach (InteractTrigger val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.hoverIcon != (Object)null && ((Object)((Component)val2).gameObject).name != "TurnOffLandmines_Interaction")
				{
					ApplyVanillaInteractionStyle(val2);
					break;
				}
			}
		}

		private void ApplyVanillaInteractionStyle(InteractTrigger source)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)source.hoverIcon == (Object)null)
			{
				return;
			}
			_vanillaInteractionIcon = source.hoverIcon;
			_vanillaInteractionLayer = ((Component)source).gameObject.layer;
			foreach (MineInteraction value in _interactions.Values)
			{
				if (value != null && !((Object)(object)value.Zone == (Object)null) && !((Object)(object)value.Trigger == (Object)null))
				{
					EnsureNativeInteractionObject(value.Zone);
					value.Trigger.hoverIcon = _vanillaInteractionIcon;
				}
			}
		}

		private void EnsureNativeInteractionObject(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return;
			}
			try
			{
				if (!string.Equals(obj.tag, "InteractTrigger", StringComparison.Ordinal))
				{
					obj.tag = "InteractTrigger";
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not assign the InteractTrigger tag to interaction zone: " + ex.Message));
			}
			int num = LayerMask.NameToLayer("InteractableObject");
			if (num < 0)
			{
				num = LayerMask.NameToLayer("Interactable");
			}
			if (num >= 0)
			{
				obj.layer = num;
			}
			else if (_vanillaInteractionLayer >= 0)
			{
				obj.layer = _vanillaInteractionLayer;
			}
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				component.isTrigger = true;
			}
		}

		private void ClearInteractions()
		{
			foreach (MineInteraction value in _interactions.Values)
			{
				StopFailureWarningBeep(value);
				if (value != null && (Object)(object)value.Zone != (Object)null)
				{
					Object.Destroy((Object)(object)value.Zone);
				}
			}
			_interactions.Clear();
		}

		private void OnDestroy()
		{
			if (_maintenanceCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_maintenanceCoroutine);
				_maintenanceCoroutine = null;
			}
			_cachedMines = null;
			UnregisterNetworkMessageHandlers();
			ClearInteractions();
			if ((Object)(object)_failureWarningBeepClip != (Object)null)
			{
				Object.Destroy((Object)(object)_failureWarningBeepClip);
			}
			_failureWarningBeepClip = null;
		}
	}
}