Decompiled source of SelectiveRadarEdit v1.0.1

BepInEx/plugins/SelectiveRadarEdit.dll

Decompiled a year ago
using System;
using System.Collections;
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LobbyCompatibility.Attributes;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using huluoboRadarEdit;

[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("SelectiveRadarEdit")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+b0986565b607868b265640cca7d041de7d3506fe")]
[assembly: AssemblyProduct("SelectiveRadarEdit")]
[assembly: AssemblyTitle("SelectiveRadarEdit")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 SelectiveRadarEdit
{
	[BepInPlugin("SelectiveRadarEdit", "SelectiveRadarEdit", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[LobbyCompatibility(/*Could not decode attribute arguments.*/)]
	public class SelectiveRadarEdit : BaseUnityPlugin
	{
		private static readonly Dictionary<string, ConfigEntry<bool>> _interiorConfigs = new Dictionary<string, ConfigEntry<bool>>();

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

		private static bool _hasLethalLevelLoader = false;

		private static bool _configInitialized = false;

		private static string _lastCheckedInterior = "";

		private static bool _loggedBlockingForCurrentInterior = false;

		public static SelectiveRadarEdit Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		public static ConfigEntry<bool> EnableFisheyeCorrection { get; private set; } = null;


		private void Awake()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			EnableFisheyeCorrection = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual Fixes", "Enable Fisheye Correction", true, "Forces the radar's fisheye lens effect to be restored. Disable if you prefer the effect off or if another mod manages it.");
			Harmony = new Harmony("SelectiveRadarEdit");
			Harmony.PatchAll();
			Logger.LogInfo((object)"SelectiveRadarEdit v1.0.1 has loaded!");
		}

		private static void EnsureConfigInitialized()
		{
			if (!_configInitialized)
			{
				Logger.LogInfo((object)"Initializing dynamic interior configuration...");
				InitializeVanillaInteriors();
				_hasLethalLevelLoader = CheckForLethalLevelLoader();
				if (_hasLethalLevelLoader)
				{
					AddLLLCustomInteriors();
				}
				_configInitialized = true;
				Logger.LogInfo((object)$"Interior configuration initialized with {_interiorConfigs.Count} entries");
			}
		}

		private static bool CheckForLethalLevelLoader()
		{
			try
			{
				Type type = Type.GetType("LethalLevelLoader.PatchedContent, LethalLevelLoader");
				return type != null;
			}
			catch
			{
				return false;
			}
		}

		private static void InitializeVanillaInteriors()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				{ "Facility", "Level1Flow" },
				{ "Facility (Extra Large)", "Level1FlowExtraLarge" },
				{ "Facility (3 Exits)", "Level1Flow3Exits" },
				{ "Haunted Mansion", "Level2Flow" },
				{ "Mineshaft", "Level3Flow" }
			};
			foreach (KeyValuePair<string, string> item in dictionary)
			{
				CreateConfigEntry(item.Key, item.Value);
			}
		}

		private static void AddLLLCustomInteriors()
		{
			try
			{
				PropertyInfo propertyInfo = Type.GetType("LethalLevelLoader.PatchedContent, LethalLevelLoader")?.GetProperty("ExtendedDungeonFlows");
				if (!(propertyInfo != null) || !(propertyInfo.GetValue(null) is IList list) || list.Count <= 0)
				{
					return;
				}
				Logger.LogInfo((object)$"Found {list.Count} ExtendedDungeonFlows from LethalLevelLoader");
				foreach (object item in list)
				{
					try
					{
						PropertyInfo property = item.GetType().GetProperty("DungeonName");
						PropertyInfo property2 = item.GetType().GetProperty("DungeonFlow");
						if (property != null && property2 != null)
						{
							string text = property.GetValue(item) as string;
							object value = property2.GetValue(item);
							string text2 = value?.GetType().GetProperty("name")?.GetValue(value) as string;
							if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && !_dungeonNameToFlowName.Values.Contains(text2))
							{
								CreateConfigEntry(text, text2);
							}
						}
					}
					catch (Exception ex)
					{
						Logger.LogWarning((object)("Failed to process ExtendedDungeonFlow: " + ex.Message));
					}
				}
			}
			catch (Exception ex2)
			{
				Logger.LogError((object)("Error accessing LethalLevelLoader data: " + ex2.Message));
			}
		}

		private static void CreateConfigEntry(string displayName, string flowName)
		{
			if (!_interiorConfigs.ContainsKey(displayName))
			{
				ConfigEntry<bool> value = ((BaseUnityPlugin)Instance).Config.Bind<bool>("Interior Settings", "Enable RadarEdit for " + displayName, false, "Whether RadarEdit effects should be enabled for " + displayName + " interior. When disabled, vanilla 2D radar will be used instead.");
				_interiorConfigs[displayName] = value;
				_dungeonNameToFlowName[displayName] = flowName;
			}
		}

		internal static void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		public static bool ShouldBlockRadarEditForCurrentInterior()
		{
			try
			{
				EnsureConfigInitialized();
				if ((Object)(object)RoundManager.Instance?.dungeonGenerator?.Generator?.DungeonFlow == (Object)null)
				{
					return false;
				}
				string name = ((Object)RoundManager.Instance.dungeonGenerator.Generator.DungeonFlow).name;
				if (_lastCheckedInterior != name)
				{
					_lastCheckedInterior = name;
					_loggedBlockingForCurrentInterior = false;
				}
				string text = null;
				foreach (KeyValuePair<string, string> item in _dungeonNameToFlowName)
				{
					if (item.Value == name)
					{
						text = item.Key;
						break;
					}
				}
				if (text != null && _interiorConfigs.TryGetValue(text, out ConfigEntry<bool> value))
				{
					bool value2 = value.Value;
					bool flag = !value2;
					if (!_loggedBlockingForCurrentInterior)
					{
						string text2 = (flag ? "RadarEdit DISABLED (using vanilla 2D radar)" : "RadarEdit ENABLED");
						Logger.LogInfo((object)("Interior: " + text + " - " + text2));
						_loggedBlockingForCurrentInterior = true;
					}
					return flag;
				}
				if (!_loggedBlockingForCurrentInterior)
				{
					Logger.LogInfo((object)("Interior: " + name + " - No config found, defaulting to RadarEdit ENABLED"));
					_loggedBlockingForCurrentInterior = true;
				}
				return false;
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Error in ShouldBlockRadarEditForCurrentInterior: " + ex.Message));
				return false;
			}
		}

		public static string GetCurrentInteriorName()
		{
			try
			{
				if ((Object)(object)RoundManager.Instance?.dungeonGenerator?.Generator?.DungeonFlow == (Object)null)
				{
					return "Unknown (not loaded)";
				}
				return ((Object)RoundManager.Instance.dungeonGenerator.Generator.DungeonFlow).name;
			}
			catch
			{
				return "Unknown (error)";
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "SelectiveRadarEdit";

		public const string PLUGIN_NAME = "SelectiveRadarEdit";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}
namespace SelectiveRadarEdit.Patches
{
	public static class RadarEditsTargets
	{
		public static readonly Type NestedRadarEditsType = AccessTools.Inner(typeof(huluoboRadarEdits), "RadarEdits");
	}
	public static class VanillaRadarValues
	{
		public const float OrthographicSize = 19.7f;

		public const float NearClipPlane = -2.47f;

		public const float FarClipPlane = 7.52f;
	}
	[HarmonyPatch]
	internal class BlockRadarEditfix
	{
		private static MethodBase TargetMethod()
		{
			if (RadarEditsTargets.NestedRadarEditsType == null)
			{
				return null;
			}
			return AccessTools.Method(RadarEditsTargets.NestedRadarEditsType, "RadarEditfix", new Type[1] { typeof(ManualCameraRenderer) }, (Type[])null);
		}

		private static bool Prefix(ManualCameraRenderer __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (((Object)(object)StartOfRound.Instance.mapScreen == (Object)(object)__instance || ((Object)((Component)__instance).gameObject).name == "TerminalScript") && SelectiveRadarEdit.ShouldBlockRadarEditForCurrentInterior())
			{
				SetupVanillaRadar(__instance);
				return false;
			}
			return true;
		}

		private static void Postfix(ManualCameraRenderer __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && ((Object)(object)StartOfRound.Instance.mapScreen == (Object)(object)__instance || ((Object)((Component)__instance).gameObject).name == "TerminalScript"))
			{
				RestoreVolumeWeightsForFishEye(__instance);
			}
		}

		private static void RestoreVolumeWeightsForFishEye(ManualCameraRenderer __instance)
		{
			try
			{
				Transform obj = ((Component)__instance.cam).transform.Find("VolumeMain (1)");
				Volume val = ((obj != null) ? ((Component)obj).GetComponent<Volume>() : null);
				if ((Object)(object)val != (Object)null && val.weight != 1f)
				{
					val.weight = 1f;
				}
				Transform val2 = ((Component)__instance.cam).transform.Find("VolumeMain (2)");
				if ((Object)(object)val2 != (Object)null)
				{
					if (!((Component)val2).gameObject.activeInHierarchy)
					{
						((Component)val2).gameObject.SetActive(true);
					}
					Volume component = ((Component)val2).GetComponent<Volume>();
					if ((Object)(object)component != (Object)null && component.weight != 1f)
					{
						component.weight = 1f;
					}
				}
			}
			catch (Exception arg)
			{
				SelectiveRadarEdit.Logger.LogError((object)$"Error in RestoreVolumeWeightsForFishEye: {arg}");
			}
		}

		private static void SetupVanillaRadar(ManualCameraRenderer __instance)
		{
			try
			{
				int mask = LayerMask.GetMask(new string[1] { "MapRadar" });
				__instance.cam.cullingMask = mask;
				__instance.cam.orthographicSize = 19.7f;
				__instance.cameraNearPlane = -2.47f;
				__instance.cameraFarPlane = 7.52f;
				__instance.cam.nearClipPlane = __instance.cameraNearPlane;
				__instance.cam.farClipPlane = __instance.cameraFarPlane;
				if ((Object)(object)__instance.mapCamera != (Object)null && (Object)(object)__instance.mapCamera != (Object)(object)__instance.cam)
				{
					__instance.mapCamera.nearClipPlane = __instance.cameraNearPlane;
					__instance.mapCamera.farClipPlane = __instance.cameraFarPlane;
					__instance.mapCamera.cullingMask = mask;
					__instance.mapCamera.orthographicSize = 19.7f;
				}
				Transform obj = ((Component)__instance.cam).transform.Find("VolumeMain (1)");
				Volume val = ((obj != null) ? ((Component)obj).GetComponent<Volume>() : null);
				if ((Object)(object)val != (Object)null)
				{
					val.weight = 1f;
				}
				Transform val2 = ((Component)__instance.cam).transform.Find("VolumeMain (2)");
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).gameObject.SetActive(true);
					Volume component = ((Component)val2).GetComponent<Volume>();
					if ((Object)(object)component != (Object)null)
					{
						component.weight = 1f;
					}
				}
			}
			catch (Exception arg)
			{
				SelectiveRadarEdit.Logger.LogError((object)$"Error in SetupVanillaRadar: {arg}");
			}
		}
	}
	[HarmonyPatch]
	internal class BlockRadarEditfix2
	{
		private static MethodBase TargetMethod()
		{
			if (RadarEditsTargets.NestedRadarEditsType == null)
			{
				return null;
			}
			return AccessTools.Method(RadarEditsTargets.NestedRadarEditsType, "RadarEditfix2", new Type[2]
			{
				typeof(ManualCameraRenderer),
				typeof(Vector3).MakeByRefType()
			}, (Type[])null);
		}

		private static bool Prefix(ManualCameraRenderer __instance, ref Vector3 pos)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (SelectiveRadarEdit.ShouldBlockRadarEditForCurrentInterior())
			{
				if ((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null)
				{
					Vector3 position = __instance.radarTargets[__instance.targetTransformIndex].transform.position;
					if ((Object)(object)__instance.targetedPlayer != (Object)null && __instance.targetedPlayer.isInHangarShipRoom)
					{
						__instance.mapCamera.nearClipPlane = -0.96f;
						__instance.mapCamera.farClipPlane = 7.52f;
						StartOfRound.Instance.radarCanvas.planeDistance = -0.93f;
					}
					else
					{
						__instance.mapCamera.nearClipPlane = -2.47f;
						__instance.mapCamera.farClipPlane = 7.52f;
						StartOfRound.Instance.radarCanvas.planeDistance = -0.93f;
					}
					((Component)__instance.mapCamera).transform.position = new Vector3(pos.x, pos.y + 3.636f, pos.z);
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal class BlockRadarEditfix3
	{
		private static MethodBase TargetMethod()
		{
			if (RadarEditsTargets.NestedRadarEditsType == null)
			{
				return null;
			}
			return AccessTools.Method(RadarEditsTargets.NestedRadarEditsType, "RadarEditfix3", new Type[1] { typeof(ManualCameraRenderer) }, (Type[])null);
		}

		private static bool Prefix(ManualCameraRenderer __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (SelectiveRadarEdit.ShouldBlockRadarEditForCurrentInterior())
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal class BlockScenefix
	{
		private static MethodBase TargetMethod()
		{
			if (RadarEditsTargets.NestedRadarEditsType == null)
			{
				return null;
			}
			return AccessTools.Method(RadarEditsTargets.NestedRadarEditsType, "Scenefix", (Type[])null, (Type[])null);
		}

		private static bool Prefix()
		{
			if (SelectiveRadarEdit.ShouldBlockRadarEditForCurrentInterior())
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ManualCameraRenderer), "Update")]
	[HarmonyPriority(0)]
	internal class RestoreVanillaFishEye
	{
		private static void Postfix(ManualCameraRenderer __instance)
		{
			if ((Object)(object)__instance == (Object)null || (!((Object)(object)StartOfRound.Instance.mapScreen == (Object)(object)__instance) && !(((Object)((Component)__instance).gameObject).name == "TerminalScript")))
			{
				return;
			}
			if (SelectiveRadarEdit.EnableFisheyeCorrection.Value)
			{
				EnsureProperVolumeWeights(__instance);
			}
			if (SelectiveRadarEdit.ShouldBlockRadarEditForCurrentInterior())
			{
				int mask = LayerMask.GetMask(new string[1] { "MapRadar" });
				if (__instance.cam.cullingMask != mask)
				{
					__instance.cam.cullingMask = mask;
				}
				if (Math.Abs(__instance.cam.orthographicSize - 19.7f) > 0.01f)
				{
					__instance.cam.orthographicSize = 19.7f;
				}
				if (Math.Abs(__instance.cam.nearClipPlane - -2.47f) > 0.01f || Math.Abs(__instance.cam.farClipPlane - 7.52f) > 0.01f)
				{
					__instance.cam.nearClipPlane = -2.47f;
					__instance.cam.farClipPlane = 7.52f;
				}
			}
		}

		private static void EnsureProperVolumeWeights(ManualCameraRenderer __instance)
		{
			try
			{
				if (!((Object)(object)__instance.lensDistortionVolume != (Object)null) || !(__instance.lensDistortionVolume.weight > 0f))
				{
					return;
				}
				Transform obj = ((Component)__instance.cam).transform.Find("VolumeMain (1)");
				Volume val = ((obj != null) ? ((Component)obj).GetComponent<Volume>() : null);
				if ((Object)(object)val != (Object)null && val.weight != 1f)
				{
					val.weight = 1f;
				}
				Transform val2 = ((Component)__instance.cam).transform.Find("VolumeMain (2)");
				if ((Object)(object)val2 != (Object)null)
				{
					if (!((Component)val2).gameObject.activeInHierarchy)
					{
						((Component)val2).gameObject.SetActive(true);
					}
					Volume component = ((Component)val2).GetComponent<Volume>();
					if ((Object)(object)component != (Object)null && component.weight != 1f)
					{
						component.weight = 1f;
					}
				}
			}
			catch (Exception arg)
			{
				SelectiveRadarEdit.Logger.LogError((object)$"Error in EnsureProperVolumeWeights: {arg}");
			}
		}
	}
}