Decompiled source of NPCDisabler v1.0.2

NPCDisabler.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Nessie.ATLYSS.EasySettings;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

[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("com.NPCDisabler.sftwre")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+22394e34d2f151bb530de6ca3d8be51778a38bc2")]
[assembly: AssemblyProduct("Player Moderation")]
[assembly: AssemblyTitle("NPCDisabler")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 NPCDisabler
{
	[BepInPlugin("com.NPCDisabler.sftwre", "NPCDisabler", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal const string EasySettingsGuid = "Nessie.ATLYSS.EasySettings";

		public static Plugin Instance;

		internal static ManualLogSource Log;

		private readonly Harmony harmony = new Harmony("com.NPCDisabler.sftwre");

		internal static readonly Dictionary<string, ConfigEntry<bool>> NpcToggles = new Dictionary<string, ConfigEntry<bool>>();

		internal static ConfigEntry<bool> DisableAllNpcs;

		private static readonly Dictionary<string, List<GameObject>> NpcRegistry = new Dictionary<string, List<GameObject>>();

		private static readonly Dictionary<string, bool> LastAppliedHiddenState = new Dictionary<string, bool>();

		private float _rescanTimer;

		private const float RescanInterval = 5f;

		internal static bool SettingsInitialized;

		private static bool _easySettingsAvailable;

		private Scene _currentTargetScene;

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			harmony.PatchAll();
			DisableAllNpcs = ((BaseUnityPlugin)this).Config.Bind<bool>("Global", "Disable All NetNPCs", false, "Hides every NetNPC discovered in your current map instance, client-side only. Overrides individual NPC toggles below while enabled.");
			DisableAllNpcs.SettingChanged += delegate
			{
				ReapplyHiddenState();
			};
			Log.LogInfo((object)"NPCDisabler v1.0.2 Loaded.");
			SceneManager.sceneLoaded += OnSceneLoaded;
			_easySettingsAvailable = Chainloader.PluginInfos.ContainsKey("Nessie.ATLYSS.EasySettings");
			if (_easySettingsAvailable)
			{
				EasySettingsIntegration.Init();
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void Update()
		{
			//IL_0002: 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)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Scene currentMapScene = GetCurrentMapScene();
			if (currentMapScene != _currentTargetScene)
			{
				_currentTargetScene = currentMapScene;
				NpcRegistry.Clear();
				LastAppliedHiddenState.Clear();
				ScanForNetNPCs();
			}
			_rescanTimer += Time.deltaTime;
			if (!(_rescanTimer < 5f))
			{
				_rescanTimer = 0f;
				ScanForNetNPCs();
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			_currentTargetScene = default(Scene);
		}

		private Scene GetCurrentMapScene()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player._mainPlayer != (Object)null && (Object)(object)Player._mainPlayer.Network_playerMapInstance != (Object)null)
			{
				Scene scene = ((Component)Player._mainPlayer.Network_playerMapInstance).gameObject.scene;
				if (((Scene)(ref scene)).isLoaded)
				{
					return scene;
				}
			}
			if ((Object)(object)Player._mainPlayer != (Object)null)
			{
				Scene scene2 = ((Component)Player._mainPlayer).gameObject.scene;
				if (((Scene)(ref scene2)).isLoaded && ((Scene)(ref scene2)).name != "DontDestroyOnLoad")
				{
					return scene2;
				}
			}
			return SceneManager.GetActiveScene();
		}

		private void ScanForNetNPCs()
		{
			//IL_0009: 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_0077: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			Scene targetScene = GetCurrentMapScene();
			if (!((Scene)(ref targetScene)).isLoaded)
			{
				return;
			}
			MapInstance targetInstance = (((Object)(object)Player._mainPlayer != (Object)null) ? Player._mainPlayer.Network_playerMapInstance : null);
			string text = "null";
			string text2 = "null";
			if ((Object)(object)Player._mainPlayer != (Object)null)
			{
				Scene scene = ((Component)Player._mainPlayer).gameObject.scene;
				text = $"{((Scene)(ref scene)).name} (handle={((Scene)(ref scene)).handle})";
				if ((Object)(object)targetInstance != (Object)null)
				{
					Scene scene2 = ((Component)targetInstance).gameObject.scene;
					text2 = $"{((Scene)(ref scene2)).name} (handle={((Scene)(ref scene2)).handle}, instanceID={((Object)targetInstance).GetInstanceID()})";
				}
			}
			NetNPC[] array = Object.FindObjectsOfType<NetNPC>(true);
			Log.LogDebug((object)(string.Format("[{0}][DEBUG] targetScene={1} (handle={2}) | ", "NPCDisabler", ((Scene)(ref targetScene)).name, ((Scene)(ref targetScene)).handle) + "playerScene=" + text + " | assignedMapInstance=" + text2 + " | " + $"totalNetNPCsInMemory={array.Length}"));
			NetNPC[] array2 = array;
			foreach (NetNPC val in array2)
			{
				Scene scene3 = ((Component)val).gameObject.scene;
				MapInstance componentInParent = ((Component)val).GetComponentInParent<MapInstance>(true);
				bool flag = scene3 == targetScene;
				bool flag2 = (Object)(object)componentInParent != (Object)null && (Object)(object)targetInstance != (Object)null && (Object)(object)componentInParent == (Object)(object)targetInstance;
				string arg = (((Object)(object)componentInParent != (Object)null) ? $"instanceID={((Object)componentInParent).GetInstanceID()}" : "NOT PARENTED under a MapInstance");
				Log.LogDebug((object)("[NPCDisabler][DEBUG]   NPC '" + GetNpcIdentifier(val) + "' in scene " + ((Scene)(ref scene3)).name + " " + $"(handle={((Scene)(ref scene3)).handle}) | parentMapInstance: {arg} | " + $"sceneMatch={flag} instanceMatch={flag2}"));
			}
			IEnumerable<NetNPC> enumerable = array.Where(delegate(NetNPC npc)
			{
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)targetInstance != (Object)null)
				{
					MapInstance componentInParent2 = ((Component)npc).GetComponentInParent<MapInstance>(true);
					if ((Object)(object)componentInParent2 != (Object)null)
					{
						return (Object)(object)componentInParent2 == (Object)(object)targetInstance;
					}
				}
				return ((Component)npc).gameObject.scene == targetScene;
			});
			bool flag3 = false;
			foreach (NetNPC item in enumerable)
			{
				string npcName = GetNpcIdentifier(item);
				if (!NpcRegistry.TryGetValue(npcName, out List<GameObject> value))
				{
					value = new List<GameObject>();
					NpcRegistry[npcName] = value;
				}
				if (!value.Contains(((Component)item).gameObject))
				{
					value.Add(((Component)item).gameObject);
				}
				if (!NpcToggles.ContainsKey(npcName))
				{
					ConfigEntry<bool> val2 = ((BaseUnityPlugin)this).Config.Bind<bool>("NPCs", npcName, false, "Hide '" + npcName + "' client-side when encountered. Does not affect other players. Overridden by 'Disable All NetNPCs' above while that's enabled.");
					NpcToggles[npcName] = val2;
					val2.SettingChanged += delegate
					{
						SetNpcHidden(npcName, IsEffectivelyHidden(npcName));
					};
					flag3 = true;
					if (_easySettingsAvailable && SettingsInitialized)
					{
						EasySettingsIntegration.AddNpcToggle(npcName, val2);
					}
				}
			}
			if (flag3)
			{
				Log.LogInfo((object)string.Format("[{0}] Discovered {1} unique NPC type(s) in scene: {2}", "NPCDisabler", NpcToggles.Count, ((Scene)(ref targetScene)).name));
			}
			ReapplyHiddenState();
		}

		private string GetNpcIdentifier(NetNPC npc)
		{
			return ((Object)((Component)npc).gameObject).name.Replace("(Clone)", string.Empty).Trim();
		}

		private static bool IsEffectivelyHidden(string npcName)
		{
			if (DisableAllNpcs.Value)
			{
				return true;
			}
			ConfigEntry<bool> value;
			return NpcToggles.TryGetValue(npcName, out value) && value.Value;
		}

		private static void SetNpcHidden(string npcName, bool hide)
		{
			if (!NpcRegistry.TryGetValue(npcName, out List<GameObject> value) || (LastAppliedHiddenState.TryGetValue(npcName, out var value2) && value2 == hide))
			{
				return;
			}
			foreach (GameObject item in value)
			{
				if (!((Object)(object)item == (Object)null))
				{
					ApplyHiddenState(item, hide);
				}
			}
			LastAppliedHiddenState[npcName] = hide;
			Log.LogInfo((object)("[NPCDisabler] " + (hide ? "Hid" : "Restored") + " '" + npcName + "' " + $"({value.Count} instance(s))."));
		}

		private static void ApplyHiddenState(GameObject npcGo, bool hide)
		{
			if (!((Object)(object)Player._mainPlayer != (Object)null) || !Player._mainPlayer._isHostPlayer)
			{
				npcGo.SetActive(!hide);
				return;
			}
			Renderer[] componentsInChildren = npcGo.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				val.enabled = !hide;
			}
			Canvas[] componentsInChildren2 = npcGo.GetComponentsInChildren<Canvas>(true);
			foreach (Canvas val2 in componentsInChildren2)
			{
				((Behaviour)val2).enabled = !hide;
			}
			CanvasGroup[] componentsInChildren3 = npcGo.GetComponentsInChildren<CanvasGroup>(true);
			foreach (CanvasGroup val3 in componentsInChildren3)
			{
				((Behaviour)val3).enabled = !hide;
			}
			Animator[] componentsInChildren4 = npcGo.GetComponentsInChildren<Animator>(true);
			foreach (Animator val4 in componentsInChildren4)
			{
				((Behaviour)val4).enabled = !hide;
			}
		}

		internal static void ReapplyHiddenState()
		{
			foreach (string key in NpcRegistry.Keys)
			{
				SetNpcHidden(key, IsEffectivelyHidden(key));
			}
		}
	}
	internal static class EasySettingsIntegration
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnSettingsInitialized;

			public static UnityAction <1>__OnSettingsApplied;
		}

		private static SettingsTab _modTab;

		private static bool _globalToggleAdded;

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

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Init()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			try
			{
				UnityEvent onInitialized = Settings.OnInitialized;
				object obj = <>O.<0>__OnSettingsInitialized;
				if (obj == null)
				{
					UnityAction val = OnSettingsInitialized;
					<>O.<0>__OnSettingsInitialized = val;
					obj = (object)val;
				}
				onInitialized.AddListener((UnityAction)obj);
				UnityEvent onApplySettings = Settings.OnApplySettings;
				object obj2 = <>O.<1>__OnSettingsApplied;
				if (obj2 == null)
				{
					UnityAction val2 = OnSettingsApplied;
					<>O.<1>__OnSettingsApplied = val2;
					obj2 = (object)val2;
				}
				onApplySettings.AddListener((UnityAction)obj2);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)"Failed to register with EasySettings! Please report this to the mod author!");
				Plugin.Log.LogWarning((object)$"Exception: {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void OnSettingsInitialized()
		{
			try
			{
				Plugin.SettingsInitialized = true;
				if (_modTab == null)
				{
					_modTab = Settings.GetOrAddCustomTab("NPCDisabler");
				}
				if (_modTab == null)
				{
					Plugin.Log.LogWarning((object)"Failed to get or add EasySettings tab.");
					return;
				}
				if (!_globalToggleAdded)
				{
					_modTab.AddHeader("Global");
					_modTab.AddToggle("Disable All NetNPCs", Plugin.DisableAllNpcs);
					_globalToggleAdded = true;
				}
				List<KeyValuePair<string, ConfigEntry<bool>>> list = (from kvp in Plugin.NpcToggles
					where !_npcNamesAddedToTab.Contains(kvp.Key)
					orderby kvp.Key
					select kvp).ToList();
				foreach (KeyValuePair<string, ConfigEntry<bool>> item in list)
				{
					_modTab.AddToggle(item.Key, item.Value);
					_npcNamesAddedToTab.Add(item.Key);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)"Failed to initialize EasySettings tab! Please report this to the mod author!");
				Plugin.Log.LogWarning((object)$"Exception: {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void OnSettingsApplied()
		{
			try
			{
				((BaseUnityPlugin)Plugin.Instance).Config.Save();
				Plugin.ReapplyHiddenState();
				Plugin.Log.LogInfo((object)"[NPCDisabler] Settings applied and saved.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)"Failed to apply EasySettings changes! Please report this to the mod author!");
				Plugin.Log.LogWarning((object)$"Exception: {arg}");
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddNpcToggle(string npcName, ConfigEntry<bool> entry)
		{
			try
			{
				if (_modTab != null && !_npcNamesAddedToTab.Contains(npcName))
				{
					_modTab.AddToggle(npcName, entry);
					_npcNamesAddedToTab.Add(npcName);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)("Failed to add EasySettings toggle for '" + npcName + "'! Please report this to the mod author!"));
				Plugin.Log.LogWarning((object)$"Exception: {arg}");
			}
		}
	}
	internal static class ModInfo
	{
		public const string GUID = "com.NPCDisabler.sftwre";

		public const string NAME = "NPCDisabler";

		public const string VERSION = "1.0.2";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}