Decompiled source of EnemiesScanner v1.0.6

EnemiesScannerMod.dll

Decompiled 9 months ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EnemiesScannerMod.Behaviours;
using EnemiesScannerMod.Models;
using EnemiesScannerMod.NetcodePatcher;
using EnemiesScannerMod.Utils;
using HarmonyLib;
using LethalLib.Modules;
using Newtonsoft.Json;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EnemiesScannerMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fe4af537e61c230fcbf9ae1e304df51fbf2a5be0")]
[assembly: AssemblyProduct("EnemiesScannerMod")]
[assembly: AssemblyTitle("EnemiesScannerMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>();
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>();
		NetworkVariableSerializationTypes.InitializeSerializer_FixedString<FixedString512Bytes>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<FixedString512Bytes>();
	}
}
namespace EnemiesScannerMod
{
	internal static class AliasesConfig
	{
		private const string FileName = "aliases.json";

		private static string _filePath;

		public static AliasesConfigObject ConfigObject { get; private set; }

		public static void Init()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (directoryName != null)
			{
				_filePath = Path.Combine(directoryName, "aliases.json");
			}
			if (!File.Exists(_filePath))
			{
				ModLogger.Instance.LogInfo((object)("Generating the default aliases config in " + _filePath));
				try
				{
					string contents = JsonConvert.SerializeObject((object)GetDefaultContentObject(), (Formatting)1);
					File.AppendAllText(_filePath, contents);
				}
				catch (Exception)
				{
					ModLogger.Instance.LogError((object)"Failed to initialize alias config file");
					ConfigObject = GetFallbackContentObject();
					throw;
				}
			}
			else
			{
				ModLogger.Instance.LogInfo((object)"Default aliases config already exists");
			}
			try
			{
				string text = File.ReadAllText(_filePath);
				ConfigObject = JsonConvert.DeserializeObject<AliasesConfigObject>(text);
			}
			catch (Exception)
			{
				ModLogger.Instance.LogError((object)"Failed to read alias config file");
				ConfigObject = GetFallbackContentObject();
				throw;
			}
			KeyValuePair<string, string>[] array = ConfigObject.Config.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<string, string> keyValuePair = array[i];
				ConfigObject.Config.Remove(keyValuePair.Key);
				ConfigObject.Config.Add(keyValuePair.Key.ToLowerInvariant(), keyValuePair.Value);
			}
		}

		public static string GetAliasOrDefault(Type type, string name)
		{
			string aliasOrDefault = GetAliasOrDefault(type);
			if (aliasOrDefault != null)
			{
				return aliasOrDefault;
			}
			return GetAliasOrDefault(name);
		}

		public static string GetAliasOrDefault(Type type)
		{
			if (!AssemblyCache.EnemyTypeToNameInvariant.TryGetValue(type, out var value))
			{
				return null;
			}
			return GetAliasOrDefault(value);
		}

		public static string GetAliasOrDefault(string name)
		{
			string value;
			return ConfigObject.Config.TryGetValue(name.ToLowerInvariant(), out value) ? value : null;
		}

		private static AliasesConfigObject GetFallbackContentObject()
		{
			return new AliasesConfigObject
			{
				Config = new Dictionary<string, string>(0)
			};
		}

		private static AliasesConfigObject GetDefaultContentObject()
		{
			return new AliasesConfigObject
			{
				Config = new Dictionary<string, string>
				{
					{ "BaboonBird", "Baboon Hawk" },
					{ "DocileLocustBees", "Roaming Locust" },
					{ "Doublewing", "Manticoil" },
					{ "Jester", "Jester" },
					{ "MaskedPlayer", "Masked" },
					{ "Nutcracker", "Nutcracker" },
					{ "Puffer", "Spore Lizard" },
					{ "SandSpider", "Bunker Spider" },
					{ "SandWorm", "Earth Leviathan" },
					{ "Blob", "Hygrodere" },
					{ "Centipede", "Snare Flea" },
					{ "Crawler", "Thumper" },
					{ "RedLocustBees", "Circuit Bee" },
					{ "DressGirl", "Ghost Girl" },
					{ "Flowerman", "Bracken" },
					{ "ForestGiant", "Forest Keeper" },
					{ "HoarderBug", "Hoarding Bug" },
					{ "MouthDog", "Eyeless Dog" },
					{ "SpringMan", "Coil-Head" }
				}
			};
		}
	}
	internal static class AssemblyCache
	{
		public static Dictionary<Type, string> EnemyTypeToNameInvariant { get; }

		static AssemblyCache()
		{
			EnemyTypeToNameInvariant = Assembly.GetAssembly(typeof(EnemyAI)).DefinedTypes.Where((TypeInfo typeInfo) => typeInfo.BaseType == typeof(EnemyAI)).ToDictionary((TypeInfo typeInfo) => typeInfo.AsType(), (TypeInfo typeInfo) => typeInfo.Name.Replace("AI", string.Empty, StringComparison.OrdinalIgnoreCase).Replace("Enemy", string.Empty, StringComparison.OrdinalIgnoreCase).ToLowerInvariant());
		}
	}
	public static class DynamicCache
	{
		public static ConcurrentDictionary<Type, string> EnemyTypeToNormalizedNames { get; } = new ConcurrentDictionary<Type, string>();

	}
	internal sealed class EnemiesScannerModNetworkManager : NetworkBehaviour
	{
		private int _shopPriceSyncValue;

		private float _batteryCapacitySyncValue;

		private FixedString512Bytes _scannerBlackListSyncValue;

		public static EnemiesScannerModNetworkManager Instance { get; private set; }

		public NetworkVariable<int> ShopPrice { get; } = new NetworkVariable<int>(20, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<bool> EnableOverheat { get; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<int> OverheatTime { get; } = new NetworkVariable<int>(120, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<int> OverheatCooldownTime { get; } = new NetworkVariable<int>(120, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<bool> EnableScanRadiusLimit { get; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<float> ScanRadiusLimit { get; } = new NetworkVariable<float>(50f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<float> BatteryCapacity { get; } = new NetworkVariable<float>(600f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<FixedString512Bytes> ScannerBlackList { get; } = new NetworkVariable<FixedString512Bytes>(FixedString512Bytes.op_Implicit(string.Empty), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public NetworkVariable<float> ScannerRefreshRate { get; } = new NetworkVariable<float>(1f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);


		public string[] ScannerBlackListNormalized { get; private set; }

		private void Awake()
		{
			//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_00b0: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			if (GameNetworkManager.Instance.isHostingGame)
			{
				ShopPrice.Value = ModConfig.ShopPriceNormalized;
				EnableOverheat.Value = ModConfig.EnableOverheat.Value;
				OverheatTime.Value = ModConfig.OverheatTime.Value;
				OverheatCooldownTime.Value = ModConfig.OverheatCooldownTime.Value;
				EnableScanRadiusLimit.Value = ModConfig.EnableScanRadiusLimit.Value;
				ScanRadiusLimit.Value = ModConfig.ScanRadiusNormalized;
				BatteryCapacity.Value = ModConfig.BatteryCapacityNormalized;
				ScannerBlackList.Value = FixedString512Bytes.op_Implicit(ModConfig.ScannerBlackListNonNull);
				ScannerRefreshRate.Value = ModConfig.ScannerRefreshRateNormalized;
				ModLogger.Instance.LogInfo((object)"Host sending config to clients");
			}
			else
			{
				_shopPriceSyncValue = ShopPrice.Value;
				_batteryCapacitySyncValue = BatteryCapacity.Value;
				_scannerBlackListSyncValue = FixedString512Bytes.op_Implicit(ModConfig.ScannerBlackListNonNull);
			}
			ScannerBlackListNormalized = ExtractScannerBlackList(ModConfig.ScannerBlackListNonNull);
			ModLogger.Instance.LogDebug((object)"ModNetworkManager Awake");
		}

		private void Update()
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			if (!GameNetworkManager.Instance.isHostingGame)
			{
				if (_shopPriceSyncValue != Instance.ShopPrice.Value)
				{
					ModLogger.Instance.LogInfo((object)$"Shop price sync in progress. Local was {_shopPriceSyncValue} | Server is {Instance.ShopPrice.Value}");
					_shopPriceSyncValue = Instance.ShopPrice.Value;
					Items.UpdateShopItemPrice(ModVariables.Instance.ScannerShopItem, Instance.ShopPrice.Value);
				}
				if (Math.Abs(_batteryCapacitySyncValue - Instance.BatteryCapacity.Value) > 0.1f)
				{
					ModLogger.Instance.LogInfo((object)$"Battery capacity sync in progress. Local was {_batteryCapacitySyncValue} | Server is {Instance.BatteryCapacity.Value}");
					_batteryCapacitySyncValue = Instance.BatteryCapacity.Value;
					ModVariables.Instance.ScannerShopItem.batteryUsage = Instance.BatteryCapacity.Value;
				}
				string value = ((FixedString512Bytes)(ref _scannerBlackListSyncValue)).Value;
				FixedString512Bytes value2 = Instance.ScannerBlackList.Value;
				if (value != ((FixedString512Bytes)(ref value2)).Value)
				{
					ModLogger.Instance.LogInfo((object)$"Scanner black list sync in progress. Local was {((FixedString512Bytes)(ref _scannerBlackListSyncValue)).Value} | Server is {Instance.ScannerBlackList.Value}");
					_scannerBlackListSyncValue = Instance.ScannerBlackList.Value;
					value2 = Instance.ScannerBlackList.Value;
					ScannerBlackListNormalized = ExtractScannerBlackList(((object)(FixedString512Bytes)(ref value2)).ToString());
				}
			}
		}

		private string[] ExtractScannerBlackList(string raw)
		{
			return raw.ToLowerInvariant().Split(';', StringSplitOptions.RemoveEmptyEntries);
		}

		protected override void __initializeVariables()
		{
			if (ShopPrice == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<ShopPrice>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)ShopPrice).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ShopPrice, "ShopPrice");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)ShopPrice);
			if (EnableOverheat == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<EnableOverheat>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)EnableOverheat).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)EnableOverheat, "EnableOverheat");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)EnableOverheat);
			if (OverheatTime == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<OverheatTime>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)OverheatTime).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)OverheatTime, "OverheatTime");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)OverheatTime);
			if (OverheatCooldownTime == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<OverheatCooldownTime>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)OverheatCooldownTime).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)OverheatCooldownTime, "OverheatCooldownTime");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)OverheatCooldownTime);
			if (EnableScanRadiusLimit == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<EnableScanRadiusLimit>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)EnableScanRadiusLimit).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)EnableScanRadiusLimit, "EnableScanRadiusLimit");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)EnableScanRadiusLimit);
			if (ScanRadiusLimit == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<ScanRadiusLimit>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)ScanRadiusLimit).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ScanRadiusLimit, "ScanRadiusLimit");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)ScanRadiusLimit);
			if (BatteryCapacity == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<BatteryCapacity>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)BatteryCapacity).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)BatteryCapacity, "BatteryCapacity");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)BatteryCapacity);
			if (ScannerBlackList == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<ScannerBlackList>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)ScannerBlackList).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ScannerBlackList, "ScannerBlackList");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)ScannerBlackList);
			if (ScannerRefreshRate == null)
			{
				throw new Exception("EnemiesScannerModNetworkManager.<ScannerRefreshRate>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)ScannerRefreshRate).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ScannerRefreshRate, "ScannerRefreshRate");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)ScannerRefreshRate);
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "EnemiesScannerModNetworkManager";
		}
	}
	internal static class ModConfig
	{
		private const string GeneralSectionName = "General";

		private const string ExperimentalSectionName = "Experimental";

		private const string EnablePingSound_Description = "Determines if ping sound should be enabled. Ping sound is played on each scan.";

		private const string ShowTopEnemiesCount_Description = "Determines how many the nearest enemies should be shown on the scanner. Min value is 1 and max value is 8.";

		private const string DisableOutsideFilter_Description = "Determines if the scanner should only display the enemies inside your location on the map. If filter enabled then if you in factory, only enemies inside factory displayed and outside enemies are ignored and vice versa. Otherwise, both enemies are always shown. This feature maybe needed for moons from the mods where enemies that shouldn't be outside are actually spawned outside.";

		private const string ShopPrice_Description = "Determines how much scanner will cost. Min value is 1 and max value is 1000.";

		private const string EnableOverheat_Description = "Determines if overheat should be enabled, so scanning will be temporary disabled on overheat. Heat is decreased when the scanner is turned off.";

		private const string OverheatTime_Description = "Determines how much time in seconds scanner could continuously work without overheat. Scanner overheat option should be enabled first. Min value is 5 and max value is 1800.";

		private const string OverheatCooldownTime_Description = "Determines how much time in seconds is needed to cool down on overheat. Scanner overheat option should be enabled first. Min value is 5 and max value is 1800.";

		private const string EnableExactDistance_Description = "Determines if the exact distance to the enemy should be shown in the scanner.";

		private const string EnableScanRadiusLimit_Description = "Determines if the scan radius should be limited to a specific value.";

		private const string ScanRadiusLimit_Description = "Determines the max radius (in meters) for a scanner. Radius limit option should be enabled first. Min value is 5 and max value is 2000.";

		private const string BatteryCapacity_Description = "Determines the battery usage (in seconds). Min value is 5 and max value is 1000.";

		private const string ScannerBlackList_Description = "Determines the list of enemies to exclude from scanning. Names should be separated by a semi-colon symbol. List is case-insensitive. You can find the list of supported technical names in the readme.";

		private const string ScannerRefreshRate_Description = "Determines the refresh rate for scanner, means scan once per N seconds (where N = value from this config). E.g. value=1 means scanner will update info once per second, value=5 means once per 5 seconds. Min value is 0.2 and max value is 100.";

		private const string ScannerBlackList_DefaultValue = "DocileLocustBees;Doublewing;Turret;";

		public static ConfigEntry<bool> EnablePingSound;

		public static ConfigEntry<int> ShowTopEnemiesCount;

		public static ConfigEntry<bool> DisableOutsideFilter;

		public static ConfigEntry<int> ShopPrice;

		public static ConfigEntry<bool> EnableOverheat;

		public static ConfigEntry<int> OverheatTime;

		public static ConfigEntry<int> OverheatCooldownTime;

		public static ConfigEntry<bool> EnableExactDistance;

		public static ConfigEntry<bool> EnableScanRadiusLimit;

		public static ConfigEntry<float> ScanRadiusLimit;

		public static ConfigEntry<float> BatteryCapacity;

		public static ConfigEntry<string> ScannerBlackList;

		public static ConfigEntry<float> ScannerRefreshRate;

		public static int ShowTopEnemiesCountNormalized => Math.Clamp(ShowTopEnemiesCount.Value, 1, 8);

		public static int ShopPriceNormalized => Math.Clamp(ShopPrice.Value, 1, 1000);

		public static float ScanRadiusNormalized => Math.Clamp(ScanRadiusLimit.Value, 5f, 2000f);

		public static float BatteryCapacityNormalized => Math.Clamp(BatteryCapacity.Value, 5f, 1000f);

		public static string ScannerBlackListNonNull => ScannerBlackList.Value ?? string.Empty;

		public static float ScannerRefreshRateNormalized => Math.Clamp(ScannerRefreshRate.Value, 0.2f, 100f);

		public static void Init()
		{
			PluginLoader.Instance.BindConfig(ref EnablePingSound, "General", "Enable scanner ping sound", defaultValue: true, "Determines if ping sound should be enabled. Ping sound is played on each scan.");
			PluginLoader.Instance.BindConfig(ref ShowTopEnemiesCount, "General", "Count of the nearest enemies shown", 5, "Determines how many the nearest enemies should be shown on the scanner. Min value is 1 and max value is 8.");
			PluginLoader.Instance.BindConfig(ref DisableOutsideFilter, "Experimental", "Disable filtering by outside enemies", defaultValue: false, "Determines if the scanner should only display the enemies inside your location on the map. If filter enabled then if you in factory, only enemies inside factory displayed and outside enemies are ignored and vice versa. Otherwise, both enemies are always shown. This feature maybe needed for moons from the mods where enemies that shouldn't be outside are actually spawned outside.");
			PluginLoader.Instance.BindConfig(ref ShopPrice, "General", "Scanner shop price", 20, "Determines how much scanner will cost. Min value is 1 and max value is 1000.");
			PluginLoader.Instance.BindConfig(ref EnableOverheat, "General", "Enable scanner overheat", defaultValue: false, "Determines if overheat should be enabled, so scanning will be temporary disabled on overheat. Heat is decreased when the scanner is turned off.");
			PluginLoader.Instance.BindConfig(ref OverheatTime, "General", "Scanner overheat timer (seconds)", 120, "Determines how much time in seconds scanner could continuously work without overheat. Scanner overheat option should be enabled first. Min value is 5 and max value is 1800.");
			PluginLoader.Instance.BindConfig(ref OverheatCooldownTime, "General", "Scanner cooldown timer (seconds)", 60, "Determines how much time in seconds is needed to cool down on overheat. Scanner overheat option should be enabled first. Min value is 5 and max value is 1800.");
			PluginLoader.Instance.BindConfig(ref EnableExactDistance, "General", "Show the exact distance to the enemy", defaultValue: true, "Determines if the exact distance to the enemy should be shown in the scanner.");
			PluginLoader.Instance.BindConfig(ref EnableScanRadiusLimit, "General", "Limit the scan radius to a specific value", defaultValue: false, "Determines if the scan radius should be limited to a specific value.");
			PluginLoader.Instance.BindConfig(ref ScanRadiusLimit, "General", "Scan radius limit (meters)", 50f, "Determines the max radius (in meters) for a scanner. Radius limit option should be enabled first. Min value is 5 and max value is 2000.");
			PluginLoader.Instance.BindConfig(ref BatteryCapacity, "General", "Battery capacity", 600f, "Determines the battery usage (in seconds). Min value is 5 and max value is 1000.");
			PluginLoader.Instance.BindConfig(ref ScannerBlackList, "General", "Enemies scan black list", "DocileLocustBees;Doublewing;Turret;", "Determines the list of enemies to exclude from scanning. Names should be separated by a semi-colon symbol. List is case-insensitive. You can find the list of supported technical names in the readme.");
			PluginLoader.Instance.BindConfig(ref ScannerRefreshRate, "Experimental", "Scanner refresh rate (seconds)", 1f, "Determines the refresh rate for scanner, means scan once per N seconds (where N = value from this config). E.g. value=1 means scanner will update info once per second, value=5 means once per 5 seconds. Min value is 0.2 and max value is 100.");
		}
	}
	internal static class ModLogger
	{
		public static ManualLogSource Instance { get; private set; }

		public static void SetInstance(ManualLogSource instance)
		{
			Instance = instance;
		}
	}
	internal sealed class ModVariables
	{
		public static ModVariables Instance { get; private set; }

		public Item ScannerShopItem { get; set; }

		public AudioClip RadarScanRound { get; set; }

		public AudioClip RadarWarningSound { get; set; }

		public AudioClip RadarAlertSound { get; set; }

		public AudioClip OverheatedSound { get; set; }

		public AudioClip RebootedSound { get; set; }

		public AudioClip NoPowerSound { get; set; }

		public AudioClip TurnOnSound { get; set; }

		public AudioClip TurnOffSound { get; set; }

		public GameObject ModNetworkManagerGameObject { get; set; }

		public static void SetInstance(ModVariables instance)
		{
			Instance = instance;
		}
	}
	[BepInPlugin("Kirpichyov.EnemiesScanner", "Kirpichyov's EnemiesScanner", "1.0.5")]
	public class PluginLoader : BaseUnityPlugin
	{
		private const string ModGuid = "Kirpichyov.EnemiesScanner";

		private const string ModName = "Kirpichyov's EnemiesScanner";

		private const string ModVersion = "1.0.5";

		private readonly Harmony _harmony = new Harmony("Kirpichyov.EnemiesScanner");

		public static PluginLoader Instance { get; private set; }

		private void Awake()
		{
			PatchNetworking();
			Instance = this;
			ModLogger.SetInstance(((BaseUnityPlugin)this).Logger);
			ModVariables.SetInstance(new ModVariables());
			ModConfig.Init();
			AliasesConfig.Init();
			RegisterModNetworkManager();
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "enemies_scanner");
			AssetBundle modBundle = AssetBundle.LoadFromFile(text);
			RegisterEnemiesScannerItem(ref modBundle, ModConfig.ShopPriceNormalized);
			InitializeSoundVariables(ref modBundle);
			_harmony.PatchAll();
			ModLogger.Instance.LogInfo((object)"Kirpichyov's EnemiesScanner loaded.");
		}

		private void RegisterEnemiesScannerItem(ref AssetBundle modBundle, int scannerPrice)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			Item val = modBundle.LoadAsset<Item>("Assets/EnemiesScannerModding/EnemiesScannerItem.asset");
			val.requiresBattery = true;
			val.automaticallySetUsingPower = false;
			val.batteryUsage = ModConfig.BatteryCapacityNormalized;
			EnemiesScannerItem enemiesScannerItem = val.spawnPrefab.AddComponent<EnemiesScannerItem>();
			((GrabbableObject)enemiesScannerItem).grabbable = true;
			((GrabbableObject)enemiesScannerItem).grabbableToEnemies = true;
			((GrabbableObject)enemiesScannerItem).insertedBattery = new Battery(false, 1f);
			((GrabbableObject)enemiesScannerItem).itemProperties = val;
			NetworkPrefabs.RegisterNetworkPrefab(val.spawnPrefab);
			Utilities.FixMixerGroups(val.spawnPrefab);
			TerminalNode val2 = ScriptableObject.CreateInstance<TerminalNode>();
			val2.clearPreviousText = true;
			val2.displayText = "Allows to scan nearby enemies\n\n";
			ModVariables.Instance.ScannerShopItem = val;
			Items.RegisterShopItem(val, (TerminalNode)null, (TerminalNode)null, val2, scannerPrice);
		}

		private void InitializeSoundVariables(ref AssetBundle modBundle)
		{
			ModVariables.Instance.RadarScanRound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/RadarScanV2.wav");
			ModVariables.Instance.RadarWarningSound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/RadarWarningV2.wav");
			ModVariables.Instance.RadarAlertSound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/RadarAlertV2.wav");
			ModVariables.Instance.OverheatedSound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/OverheatWithRobot.wav");
			ModVariables.Instance.RebootedSound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/Rebooted.wav");
			ModVariables.Instance.NoPowerSound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/OutOfBattery.ogg");
			ModVariables.Instance.TurnOnSound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/detector_radio_on.ogg");
			ModVariables.Instance.TurnOffSound = modBundle.LoadAsset<AudioClip>("Assets/EnemiesScannerModding/detector_radio_off.ogg");
		}

		private void RegisterModNetworkManager()
		{
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "enemiesscanner_netcodemod");
			AssetBundle val = AssetBundle.LoadFromFile(text);
			GameObject val2 = val.LoadAsset<GameObject>("Assets/EnemiesScannerNetcode/EnemiesScannerNetworkManager.prefab");
			val2.AddComponent<EnemiesScannerModNetworkManager>();
			ModVariables.Instance.ModNetworkManagerGameObject = val2;
		}

		private void PatchNetworking()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}

		public void BindConfig<T>(ref ConfigEntry<T> config, string section, string key, T defaultValue, string description = "")
		{
			config = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description);
		}
	}
}
namespace EnemiesScannerMod.Utils
{
	internal static class StringUtils
	{
		public static string GetCloseIndicator(DangerLevel dangerLevel)
		{
			if (1 == 0)
			{
			}
			string result = dangerLevel switch
			{
				DangerLevel.Death => "<color=#ff0000>LETHAL</color>", 
				DangerLevel.Danger => "<color=#ff6f00>DANGER</color>", 
				DangerLevel.Near => "<color=#fff200>NEAR</color>", 
				DangerLevel.Far => "<color=#ffffff>FAR</color>", 
				_ => "TOO FAR", 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		public static string GetActiveOrDisableString(bool value)
		{
			return value ? "activated" : "disabled";
		}

		public static string SanitizeEnemyDisplayName(string original)
		{
			return original.Replace("(Clone)", string.Empty).Replace("Script", string.Empty).Replace("Enemy", string.Empty)
				.Replace("AI", string.Empty)
				.Replace("Prefab", string.Empty);
		}

		public static string SanitizeEnemyTypeName(string original)
		{
			return original.Replace("Script", string.Empty).Replace("Enemy", string.Empty).Replace("AI", string.Empty);
		}
	}
}
namespace EnemiesScannerMod.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void AddToPrefabs(ref GameNetworkManager __instance)
		{
			((Component)__instance).GetComponent<NetworkManager>().AddNetworkPrefab(ModVariables.Instance.ModNetworkManagerGameObject);
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void SpawnNetManager(StartOfRound __instance)
		{
			if (((NetworkBehaviour)__instance).IsHost)
			{
				GameObject val = Object.Instantiate<GameObject>(ModVariables.Instance.ModNetworkManagerGameObject);
				val.GetComponent<NetworkObject>().Spawn(false);
			}
		}
	}
}
namespace EnemiesScannerMod.Models
{
	internal sealed class AliasesConfigObject
	{
		public Dictionary<string, string> Config { get; set; }
	}
	public enum DangerLevel
	{
		TooFar,
		Far,
		Near,
		Danger,
		Death
	}
	internal sealed class EnemyScanSummary
	{
		public string Name { get; set; }

		public string AliasName { get; set; }

		public Vector3 Position { get; set; }

		public float Distance { get; set; }

		public char UpDownIndicator { get; set; }

		public RelativeLevel RelativeLevel { get; set; }

		public bool IsOutsideType { get; set; }

		public DangerLevel DangerLevel { get; set; }

		public static EnemyScanSummary CreateFromEnemy(EnemyAI enemy, Vector3 playerPosition)
		{
			//IL_0007: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			Vector3 position = ((Component)enemy).transform.position;
			RelativeLevel relativeLevel = GetRelativeLevel(position, playerPosition);
			float distance = Vector3.Distance(position, playerPosition);
			string name = StringUtils.SanitizeEnemyDisplayName(((Object)enemy).name);
			return new EnemyScanSummary
			{
				Name = name,
				AliasName = AliasesConfig.GetAliasOrDefault(((object)enemy).GetType(), name),
				Position = position,
				Distance = distance,
				RelativeLevel = relativeLevel,
				UpDownIndicator = GetUpDownIndicator(relativeLevel),
				IsOutsideType = enemy.enemyType.isOutsideEnemy,
				DangerLevel = GetDangerLevel(distance)
			};
		}

		public static EnemyScanSummary CreateFromTurret(Turret enemy, Vector3 playerPosition)
		{
			//IL_0007: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			Vector3 position = ((Component)enemy).transform.position;
			RelativeLevel relativeLevel = GetRelativeLevel(position, playerPosition);
			float distance = Vector3.Distance(position, playerPosition);
			string name = StringUtils.SanitizeEnemyDisplayName(((Object)enemy).name);
			return new EnemyScanSummary
			{
				Name = name,
				AliasName = AliasesConfig.GetAliasOrDefault(((object)enemy).GetType(), name),
				Position = position,
				Distance = distance,
				RelativeLevel = relativeLevel,
				UpDownIndicator = GetUpDownIndicator(relativeLevel),
				IsOutsideType = false,
				DangerLevel = GetDangerLevel(distance)
			};
		}

		private static char GetUpDownIndicator(RelativeLevel level)
		{
			return level switch
			{
				RelativeLevel.Lower => 'v', 
				RelativeLevel.Upper => '^', 
				_ => '-', 
			};
		}

		private static RelativeLevel GetRelativeLevel(Vector3 a, Vector3 b)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			float num = a.y - b.y;
			if (num < 0f && num <= -5f)
			{
				return RelativeLevel.Lower;
			}
			if (num > 0f && num >= 5f)
			{
				return RelativeLevel.Upper;
			}
			return RelativeLevel.Same;
		}

		private static DangerLevel GetDangerLevel(float distance)
		{
			if (distance <= 8f)
			{
				return DangerLevel.Death;
			}
			if (distance > 8f && distance <= 14f)
			{
				return DangerLevel.Danger;
			}
			if (distance > 14f && distance <= 20f)
			{
				return DangerLevel.Near;
			}
			if (distance > 20f && distance <= 30f)
			{
				return DangerLevel.Far;
			}
			return DangerLevel.TooFar;
		}
	}
	public enum RelativeLevel
	{
		Same,
		Upper,
		Lower
	}
}
namespace EnemiesScannerMod.Behaviours
{
	public class EnemiesScannerItem : PhysicsProp
	{
		private enum LedState
		{
			Disabled,
			NoDanger,
			Warning,
			Danger
		}

		private const string DefaultScreenText = "Scan in progress...";

		private const string DefaultCounterText = "0";

		private Light _defaultLed;

		private Light _warningLed;

		private Light _dangerLed;

		private Light[] _leds;

		private TextMeshProUGUI _screenText;

		private TextMeshProUGUI _counterText;

		private DateTime _lastScan = DateTime.MinValue;

		private AudioSource _audioSource;

		private float _heatValue;

		private Coroutine _cooldownCoroutine;

		private Image _heatImage;

		private Canvas _screenCanvas;

		private Canvas _counterCanvas;

		private GameObject _heatUI;

		private bool IsOverheat => EnemiesScannerModNetworkManager.Instance.EnableOverheat.Value && _heatValue >= (float)EnemiesScannerModNetworkManager.Instance.OverheatTime.Value;

		private static bool IsScannerExcludeTurrets => EnemiesScannerModNetworkManager.Instance.ScannerBlackListNormalized.Contains("turret");

		private void Awake()
		{
			Light[] componentsInChildren = ((Component)this).GetComponentsInChildren<Light>(true);
			Light[] array = componentsInChildren;
			foreach (Light val in array)
			{
				((Behaviour)val).enabled = false;
			}
			_defaultLed = componentsInChildren.First((Light l) => ((Object)((Component)l).gameObject).name == "DefaultLed");
			_defaultLed.intensity = 1f;
			_warningLed = componentsInChildren.First((Light l) => ((Object)((Component)l).gameObject).name == "WarningLed");
			_warningLed.intensity = 1f;
			_dangerLed = componentsInChildren.First((Light l) => ((Object)((Component)l).gameObject).name == "DangerLed");
			_dangerLed.intensity = 2f;
			_leds = (Light[])(object)new Light[3] { _defaultLed, _warningLed, _dangerLed };
			_audioSource = ((Component)this).GetComponent<AudioSource>();
			TextMeshProUGUI[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<TextMeshProUGUI>();
			Canvas[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Canvas>();
			_screenText = componentsInChildren2.First((TextMeshProUGUI t) => ((Object)((Component)t).gameObject).name == "ScreenText");
			_screenCanvas = componentsInChildren3.First((Canvas t) => ((Object)((Component)t).gameObject).name == "ScreenCanvas");
			((Behaviour)_screenCanvas).enabled = false;
			((TMP_Text)_screenText).fontSize = 18f;
			((TMP_Text)_screenText).fontStyle = (FontStyles)0;
			((TMP_Text)_screenText).SetText("Scan in progress...", true);
			_counterText = componentsInChildren2.First((TextMeshProUGUI t) => ((Object)((Component)t).gameObject).name == "CounterText");
			_counterCanvas = componentsInChildren3.First((Canvas t) => ((Object)((Component)t).gameObject).name == "CounterCanvas");
			((Behaviour)_counterCanvas).enabled = false;
			((TMP_Text)_counterText).fontSize = 16f;
			((TMP_Text)_counterText).SetText("0", true);
			_heatImage = ((Component)this).GetComponentsInChildren<Image>().First((Image i) => ((Object)((Component)i).gameObject).name == "OverheatImageRed");
			_heatUI = ((Component)((Component)this).GetComponentsInChildren<RectTransform>().First((RectTransform t) => ((Object)((Component)t).gameObject).name == "OverheatUI")).gameObject;
			_heatValue = 0f;
			_cooldownCoroutine = null;
		}

		public override void Start()
		{
			((GrabbableObject)this).Start();
			bool value = EnemiesScannerModNetworkManager.Instance.EnableOverheat.Value;
			_heatUI.SetActive(value);
			((Behaviour)_heatImage).enabled = value;
			_heatImage.fillAmount = 0f;
		}

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			ItemActivateInternal(used, buttonDown, isLocal: false);
		}

		public override void UseUpBatteries()
		{
			((GrabbableObject)this).UseUpBatteries();
			_audioSource.PlayOneShot(ModVariables.Instance.NoPowerSound, 0.6f);
			DisableLeds();
			TurnOff(used: false);
		}

		public override void PocketItem()
		{
			((GrabbableObject)this).PocketItem();
			TurnOff(((GrabbableObject)this).isBeingUsed);
		}

		public override void EquipItem()
		{
			((PhysicsProp)this).EquipItem();
			if (((GrabbableObject)this).isBeingUsed)
			{
				SwitchLed(LedState.NoDanger);
				((Behaviour)_screenCanvas).enabled = true;
				((Behaviour)_counterCanvas).enabled = true;
				((TMP_Text)_screenText).SetText("Scan in progress...", true);
			}
		}

		public override void Update()
		{
			((GrabbableObject)this).Update();
			if (IsOverheat)
			{
				if (((GrabbableObject)this).isBeingUsed)
				{
					_audioSource.PlayOneShot(ModVariables.Instance.OverheatedSound, 0.5f);
					TurnOff(used: false);
				}
				return;
			}
			if (((GrabbableObject)this).isBeingUsed && IsDelayPass(_lastScan, EnemiesScannerModNetworkManager.Instance.ScannerRefreshRate.Value))
			{
				ScanEnemies();
			}
			if (EnemiesScannerModNetworkManager.Instance.EnableOverheat.Value)
			{
				if (((GrabbableObject)this).isBeingUsed)
				{
					float heat = Mathf.Clamp(_heatValue + Time.deltaTime, 0f, (float)EnemiesScannerModNetworkManager.Instance.OverheatTime.Value);
					SetHeat(heat);
				}
				else
				{
					float heat2 = Mathf.Clamp(_heatValue - Time.deltaTime, 0f, (float)EnemiesScannerModNetworkManager.Instance.OverheatTime.Value);
					SetHeat(heat2);
				}
			}
		}

		private void ItemActivateInternal(bool used, bool buttonDown, bool isLocal)
		{
			if (!buttonDown || (Object)(object)((GrabbableObject)this).playerHeldBy == (Object)null)
			{
				return;
			}
			((GrabbableObject)this).isBeingUsed = !((GrabbableObject)this).isBeingUsed;
			if (((GrabbableObject)this).isBeingUsed && IsOverheat)
			{
				_audioSource.PlayOneShot(ModVariables.Instance.OverheatedSound, 0.5f);
				TurnOff(used: false);
				return;
			}
			_audioSource.PlayOneShot(((GrabbableObject)this).isBeingUsed ? ModVariables.Instance.TurnOnSound : ModVariables.Instance.TurnOffSound);
			SwitchLed(((GrabbableObject)this).isBeingUsed ? LedState.NoDanger : LedState.Disabled);
			((Behaviour)_screenCanvas).enabled = ((GrabbableObject)this).isBeingUsed && !((GrabbableObject)this).isPocketed;
			((Behaviour)_counterCanvas).enabled = ((GrabbableObject)this).isBeingUsed && !((GrabbableObject)this).isPocketed;
			if (!isLocal)
			{
				ItemActivateServerRpc(used, buttonDown: true);
			}
		}

		private void TurnOff(bool used)
		{
			if (!used)
			{
				((GrabbableObject)this).isBeingUsed = false;
			}
			DisableLeds();
			((Behaviour)_screenCanvas).enabled = false;
			((Behaviour)_counterCanvas).enabled = false;
		}

		private void SwitchLed(LedState ledState)
		{
			DisableLeds();
			if (!((GrabbableObject)this).isPocketed)
			{
				switch (ledState)
				{
				case LedState.NoDanger:
					((Behaviour)_defaultLed).enabled = true;
					break;
				case LedState.Warning:
					((Behaviour)_warningLed).enabled = true;
					break;
				case LedState.Danger:
					((Behaviour)_dangerLed).enabled = true;
					break;
				}
			}
		}

		private void DisableLeds()
		{
			Light[] leds = _leds;
			foreach (Light val in leds)
			{
				((Behaviour)val).enabled = false;
			}
		}

		[ServerRpc]
		public void ItemActivateServerRpc(bool used, bool buttonDown)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Invalid comparison between Unknown and I4
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Invalid comparison between Unknown and I4
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (((NetworkBehaviour)this).OwnerClientId != networkManager.LocalClientId)
				{
					if ((int)networkManager.LogLevel <= 1)
					{
						Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
					}
					return;
				}
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3368946315u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref used, default(ForPrimitives));
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref buttonDown, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3368946315u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				NetworkManager networkManager2 = ((NetworkBehaviour)this).NetworkManager;
				if (!((Object)(object)networkManager2 == (Object)null) && networkManager2.IsListening)
				{
					ItemActivateClientRpc(used, buttonDown);
				}
			}
		}

		[ClientRpc]
		public void ItemActivateClientRpc(bool used, bool buttonDown)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1925067959u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref used, default(ForPrimitives));
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref buttonDown, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1925067959u, val, (RpcDelivery)0);
			}
			if ((int)((NetworkBehaviour)this).__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				NetworkManager networkManager2 = ((NetworkBehaviour)this).NetworkManager;
				if (!((Object)(object)networkManager2 == (Object)null) && networkManager2.IsListening && !((NetworkBehaviour)this).IsOwner)
				{
					ItemActivateInternal(used, buttonDown, isLocal: true);
				}
			}
		}

		private void ScanEnemies()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			_lastScan = DateTime.UtcNow;
			Vector3 selfPosition = ((Component)this).transform.position;
			bool isOutside = !((GrabbableObject)this).isInFactory;
			ModLogger.Instance.LogDebug((object)$"Player position: {selfPosition}");
			Func<EnemyAI, bool> predicate = (ModConfig.DisableOutsideFilter.Value ? ((Func<EnemyAI, bool>)((EnemyAI enemy) => true)) : ((Func<EnemyAI, bool>)((EnemyAI enemy) => isOutside ? enemy.isOutside : (!enemy.isOutside))));
			Func<Turret, bool> predicate2 = (ModConfig.DisableOutsideFilter.Value ? ((Func<Turret, bool>)((Turret enemy) => true)) : ((Func<Turret, bool>)((Turret enemy) => !isOutside)));
			Func<EnemyScanSummary, bool> predicate3 = (EnemiesScannerModNetworkManager.Instance.EnableScanRadiusLimit.Value ? ((Func<EnemyScanSummary, bool>)((EnemyScanSummary summary) => summary.Distance <= EnemiesScannerModNetworkManager.Instance.ScanRadiusLimit.Value)) : ((Func<EnemyScanSummary, bool>)((EnemyScanSummary summary) => true)));
			IEnumerable<EnemyScanSummary> first = from enemy in (from enemy in Object.FindObjectsOfType<EnemyAI>()
					where !IsExcludeCreature(enemy)
					where !enemy.isEnemyDead
					select enemy).Where(predicate)
				select EnemyScanSummary.CreateFromEnemy(enemy, selfPosition);
			IEnumerable<EnemyScanSummary> enumerable;
			if (!IsScannerExcludeTurrets)
			{
				enumerable = from enemy in Object.FindObjectsOfType<Turret>().Where(predicate2)
					select EnemyScanSummary.CreateFromTurret(enemy, selfPosition);
			}
			else
			{
				IEnumerable<EnemyScanSummary> enumerable2 = Array.Empty<EnemyScanSummary>();
				enumerable = enumerable2;
			}
			IEnumerable<EnemyScanSummary> second = enumerable;
			EnemyScanSummary[] array = first.Concat(second).Where(predicate3).ToArray();
			EnemyScanSummary[] array2 = array.OrderBy((EnemyScanSummary enemy) => enemy.Distance).Take(ModConfig.ShowTopEnemiesCountNormalized).ToArray();
			((TMP_Text)_counterText).SetText($"{array.Length}", true);
			if (array2.Length == 0)
			{
				((TMP_Text)_screenText).SetText("No enemies nearby...", true);
				return;
			}
			SwitchLed(LedState.NoDanger);
			if (array2.Any((EnemyScanSummary s) => s.RelativeLevel == RelativeLevel.Same && s.DangerLevel == DangerLevel.Death))
			{
				SwitchLed(LedState.Danger);
				_audioSource.PlayOneShot(ModVariables.Instance.RadarAlertSound, 0.6f);
			}
			else if (array2.Any((EnemyScanSummary s) => s.RelativeLevel == RelativeLevel.Same && s.DangerLevel == DangerLevel.Danger))
			{
				SwitchLed(LedState.Warning);
				_audioSource.PlayOneShot(ModVariables.Instance.RadarWarningSound, 0.5f);
			}
			else if (ModConfig.EnablePingSound.Value)
			{
				_audioSource.PlayOneShot(ModVariables.Instance.RadarScanRound, 0.3f);
			}
			StringBuilder stringBuilder = new StringBuilder();
			EnemyScanSummary[] array3 = array2;
			foreach (EnemyScanSummary enemyScanSummary in array3)
			{
				ModLogger.Instance.LogDebug((object)$"[SCAN] {enemyScanSummary.Name} | {enemyScanSummary.Distance}/{enemyScanSummary.Position} | {enemyScanSummary.UpDownIndicator}");
				AppendScannerEntryLine(stringBuilder, enemyScanSummary);
			}
			((TMP_Text)_screenText).SetText(stringBuilder.ToString(), true);
		}

		private void SetHeat(float newValue)
		{
			_heatValue = newValue;
			float num = _heatValue / (float)EnemiesScannerModNetworkManager.Instance.OverheatTime.Value;
			_heatImage.fillAmount = Mathf.Clamp(num, 0f, (float)EnemiesScannerModNetworkManager.Instance.OverheatTime.Value);
			if (IsOverheat && _cooldownCoroutine == null)
			{
				_cooldownCoroutine = ((MonoBehaviour)this).StartCoroutine(StartCooldown());
			}
		}

		private IEnumerator StartCooldown()
		{
			yield return (object)new WaitForSeconds((float)EnemiesScannerModNetworkManager.Instance.OverheatCooldownTime.Value);
			SetHeat(0f);
			_cooldownCoroutine = null;
			_audioSource.PlayOneShot(ModVariables.Instance.RebootedSound, 0.5f);
		}

		private static void AppendScannerEntryLine(StringBuilder stringBuilder, EnemyScanSummary s)
		{
			stringBuilder.Append(StringUtils.GetCloseIndicator(s.DangerLevel) + " | ");
			stringBuilder.Append((s.AliasName ?? s.Name) + " | ");
			if (ModConfig.EnableExactDistance.Value)
			{
				stringBuilder.Append($"{s.Distance:F2} | ");
			}
			stringBuilder.Append(s.UpDownIndicator);
			stringBuilder.AppendLine();
		}

		private static bool IsExcludeCreature(EnemyAI enemy)
		{
			Type type = ((object)enemy).GetType();
			if (AssemblyCache.EnemyTypeToNameInvariant.TryGetValue(type, out var value))
			{
				return EnemiesScannerModNetworkManager.Instance.ScannerBlackListNormalized.Contains(value);
			}
			if (DynamicCache.EnemyTypeToNormalizedNames.TryGetValue(type, out var value2))
			{
				return EnemiesScannerModNetworkManager.Instance.ScannerBlackListNormalized.Contains(value2);
			}
			string text = StringUtils.SanitizeEnemyTypeName(type.Name);
			DynamicCache.EnemyTypeToNormalizedNames.TryAdd(type, text.ToLowerInvariant());
			ModLogger.Instance.LogInfo((object)("[Notice] Non vanilla game creature detected! You could use '" + text + "' name in the scanner blacklist config if you want to hide it. For alias config you could use '" + StringUtils.SanitizeEnemyDisplayName(((Object)enemy).name) + "' name."));
			return EnemiesScannerModNetworkManager.Instance.ScannerBlackListNormalized.Contains(text.ToLowerInvariant());
		}

		private static bool IsDelayPass(DateTime reference, float? customDelaySeconds = null)
		{
			return (DateTime.UtcNow - reference).TotalSeconds > (double)customDelaySeconds.GetValueOrDefault(1f);
		}

		protected override void __initializeVariables()
		{
			((PhysicsProp)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_EnemiesScannerItem()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(3368946315u, new RpcReceiveHandler(__rpc_handler_3368946315));
			NetworkManager.__rpc_func_table.Add(1925067959u, new RpcReceiveHandler(__rpc_handler_1925067959));
		}

		private static void __rpc_handler_3368946315(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if (rpcParams.Server.Receive.SenderClientId != target.OwnerClientId)
			{
				if ((int)networkManager.LogLevel <= 1)
				{
					Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
				}
			}
			else
			{
				bool used = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref used, default(ForPrimitives));
				bool buttonDown = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref buttonDown, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((EnemiesScannerItem)(object)target).ItemActivateServerRpc(used, buttonDown);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1925067959(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool used = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref used, default(ForPrimitives));
				bool buttonDown = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref buttonDown, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((EnemiesScannerItem)(object)target).ItemActivateClientRpc(used, buttonDown);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "EnemiesScannerItem";
		}
	}
}
namespace EnemiesScannerMod.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}