Decompiled source of TimerMod v1.1.1

TimerPlugin.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
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 Microsoft.CodeAnalysis;
using Photon.Pun;
using TMPro;
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("TimerPlugin")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("Timer Plugin")]
[assembly: AssemblyTitle("TimerPlugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TimerPlugin
{
	public class TimerPlugin_Config
	{
		private readonly ConfigFile _configFile;

		public static ConfigEntry<bool> configPluginEnabled;

		public static ConfigEntry<bool> configLevelTimerEnabled;

		public static ConfigEntry<bool> configIdleCountdownEnabled;

		public static ConfigEntry<bool> configEnemyTimerEnabled;

		public static ConfigEntry<string> configEnemyShowType;

		public TimerPlugin_Config(ConfigFile configFile)
		{
			_configFile = configFile;
		}

		public void RegisterOptions()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			configPluginEnabled = _configFile.Bind<bool>("General", "PluginEnabled", true, new ConfigDescription("If enabled, plugin will be loaded", (AcceptableValueBase)(object)new AcceptableValueList<bool>(new bool[2] { true, false }), Array.Empty<object>()));
			configLevelTimerEnabled = _configFile.Bind<bool>("Timers", "TimerEnabled", true, new ConfigDescription("If enabled, level timer will be shown", (AcceptableValueBase)(object)new AcceptableValueList<bool>(new bool[2] { true, false }), Array.Empty<object>()));
			configIdleCountdownEnabled = _configFile.Bind<bool>("Timers", "CountdownEnabled", true, new ConfigDescription("If enabled, enemies' idle time will be shown", (AcceptableValueBase)(object)new AcceptableValueList<bool>(new bool[2] { true, false }), Array.Empty<object>()));
			configEnemyTimerEnabled = _configFile.Bind<bool>("Timers", "EnemyTimerEnabled", true, new ConfigDescription("If enabled, enemies' respawn time will be shown", (AcceptableValueBase)(object)new AcceptableValueList<bool>(new bool[2] { true, false }), Array.Empty<object>()));
			configEnemyShowType = _configFile.Bind<string>("Timers.Enemy", "EnemyTimerShowType", "ALL", new ConfigDescription("What to show on enemy list\nEnemyList - Shows what enemies are on level\nAlive - Enemy displayed only if it's alive\nDead - Enemy displayed only if it's dead(without time)\nDeadTimer - Shows dead enemies with respawn times\nALL - Shows all info", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5] { "ALL", "Alive", "Dead", "DeadTimer", "EnemyList" }), Array.Empty<object>()));
		}
	}
	public class EnemyListUI : SemiUI
	{
		private TextMeshProUGUI enemyNames;

		private TextMeshProUGUI respawnTimes;

		private TextMeshProUGUI header;

		public GameObject scanlineObject;

		private float showBigMessage;

		private bool fetched;

		public static EnemyListUI instance;

		private FieldInfo showTimerField;

		public float despawnedTimer;

		private string colorTier1;

		private string colorTier2;

		private string colorTier3;

		private string enemyToShow;

		private Difficulty difficultyToShow;

		protected override void Start()
		{
			//IL_001d: 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)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			((SemiUI)this).Start();
			colorTier1 = ColorUtility.ToHtmlStringRGB(new Color(0.3373f, 1f, 0.4275f, 1f));
			colorTier2 = ColorUtility.ToHtmlStringRGB(new Color(1f, 0.5529f, 0f, 1f));
			colorTier3 = ColorUtility.ToHtmlStringRGB(new Color(0.8f, 0f, 0f, 1f));
			showTimerField = typeof(SemiUI).GetField("showTimer", BindingFlags.Instance | BindingFlags.NonPublic);
			instance = this;
			enemyNames = ((Component)this).GetComponent<TextMeshProUGUI>();
			respawnTimes = ((Component)((Component)this).transform.Find("RespawnTimes")).GetComponent<TextMeshProUGUI>();
			header = ((Component)((Component)this).transform.Find("Enemies Header")).GetComponent<TextMeshProUGUI>();
			((TMP_Text)enemyNames).text = "";
			((TMP_Text)respawnTimes).text = "";
			((TMP_Text)header).text = "Enemies";
			((TMP_Text)respawnTimes).alignment = (TextAlignmentOptions)2049;
			((TMP_Text)respawnTimes).enableWordWrapping = false;
			((TMP_Text)respawnTimes).overflowMode = (TextOverflowModes)0;
			((Behaviour)header).enabled = false;
			scanlineObject.SetActive(false);
			base.showPosition = new Vector2(240f, 85f);
			base.hidePosition = new Vector2(390f, 85f);
		}

		public string GetDifficultyColor(Difficulty difficulty)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected I4, but got Unknown
			return (int)difficulty switch
			{
				0 => colorTier1, 
				1 => colorTier2, 
				2 => colorTier3, 
				_ => "FFFFFF", 
			};
		}

		public void Fetch()
		{
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)enemyNames).text = "";
			((TMP_Text)respawnTimes).text = "";
			((Behaviour)header).enabled = false;
			scanlineObject.SetActive(false);
			foreach (EnemyParent item in EnemyDirector.instance.enemiesSpawned)
			{
				float num = item.DespawnedTimer;
				bool flag = SemiFunc.IsNotMasterClient();
				if (flag)
				{
					num = (item.EnableObject.activeSelf ? 0f : 1f);
				}
				if ((double)num <= 1E-06)
				{
					if (TimerPlugin_Config.configEnemyShowType.Value == "Alive" || TimerPlugin_Config.configEnemyShowType.Value == "EnemyList" || TimerPlugin_Config.configEnemyShowType.Value == "ALL")
					{
						TextMeshProUGUI val = enemyNames;
						((TMP_Text)val).text = ((TMP_Text)val).text + "<color=#" + GetDifficultyColor(item.difficulty) + ">" + item.enemyName + "</color>\n";
						if (TimerPlugin_Config.configEnemyShowType.Value == "ALL")
						{
							TextMeshProUGUI obj = respawnTimes;
							((TMP_Text)obj).text = ((TMP_Text)obj).text + "<b>Alive</b>\n";
						}
					}
				}
				else
				{
					if (!(TimerPlugin_Config.configEnemyShowType.Value != "Alive"))
					{
						continue;
					}
					TextMeshProUGUI val = enemyNames;
					((TMP_Text)val).text = ((TMP_Text)val).text + "<color=#" + GetDifficultyColor(item.difficulty) + ">" + item.enemyName + "</color>\n";
					if (TimerPlugin_Config.configEnemyShowType.Value == "DeadTimer" || TimerPlugin_Config.configEnemyShowType.Value == "ALL")
					{
						if (flag)
						{
							TextMeshProUGUI obj2 = respawnTimes;
							((TMP_Text)obj2).text = ((TMP_Text)obj2).text + "<b>Dead</b>\n";
						}
						else
						{
							TextMeshProUGUI obj3 = respawnTimes;
							((TMP_Text)obj3).text = ((TMP_Text)obj3).text + $"<b>{num:F1}s</b>\n";
						}
					}
				}
			}
			if (((TMP_Text)enemyNames).text != "")
			{
				((Behaviour)header).enabled = true;
				scanlineObject.SetActive(true);
			}
		}

		public void BigMessage(string enemyName, Difficulty difficulty)
		{
			//IL_0009: 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)
			enemyToShow = enemyName;
			difficultyToShow = difficulty;
			showBigMessage = 2f;
		}

		protected override void Update()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (!TimerPlugin_Config.configEnemyTimerEnabled.Value)
			{
				((SemiUI)this).Hide();
				return;
			}
			((SemiUI)this).Update();
			((SemiUI)this).Hide();
			if (showBigMessage > 0f)
			{
				showBigMessage -= Time.deltaTime;
				SemiFunc.UIBigMessage("<color=#" + GetDifficultyColor(difficultyToShow) + ">" + enemyToShow + "</color> respawned", "{!}", 20f, Color.white, Color.white);
			}
			if ((float)showTimerField.GetValue(this) > 0f)
			{
				if (!fetched)
				{
					Fetch();
				}
			}
			else
			{
				fetched = false;
			}
		}
	}
	public class IdleCountdownUI : SemiUI
	{
		public static IdleCountdownUI instance;

		private TextMeshProUGUI Text;

		private bool setup = true;

		private bool isIdle = true;

		public static FieldInfo spawnIdleTimerField;

		protected override void Start()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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)
			((SemiUI)this).Start();
			instance = this;
			spawnIdleTimerField = AccessTools.Field(typeof(EnemyDirector), "spawnIdlePauseTimer");
			Text = ((Component)this).GetComponent<TextMeshProUGUI>();
			((TMP_Text)Text).text = "00:00";
			((Graphic)Text).color = new Color(1f, 0.4f, 0.2f, 1f);
			((TMP_Text)Text).fontSize = 18f;
			base.showPosition = new Vector2(-330f, 100f);
			base.hidePosition = new Vector2(-430f, 100f);
		}

		protected override void Update()
		{
			((SemiUI)this).Update();
			if (!isIdle || !TimerPlugin_Config.configIdleCountdownEnabled.Value)
			{
				((SemiUI)this).Hide();
			}
			else if (setup)
			{
				if (LevelGenerator.Instance.Generated)
				{
					setup = false;
				}
			}
			else if (!((Object)(object)Text == (Object)null))
			{
				float num = (float)spawnIdleTimerField.GetValue(EnemyDirector.instance);
				if (num <= 0f)
				{
					((TMP_Text)Text).text = "No Idle";
					isIdle = false;
				}
				else
				{
					int num2 = Mathf.FloorToInt(num / 60f);
					int num3 = Mathf.FloorToInt(num % 60f);
					((TMP_Text)Text).text = $"{num2:00}:{num3:00}";
				}
			}
		}
	}
	public class LevelTimerUI : SemiUI
	{
		public static LevelTimerUI instance;

		private TextMeshProUGUI Text;

		private bool setup = true;

		private float levelTimerElapsedTime;

		protected override void Start()
		{
			//IL_0045: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			((SemiUI)this).Start();
			instance = this;
			Text = ((Component)this).GetComponent<TextMeshProUGUI>();
			((TMP_Text)Text).text = "00:00";
			((Graphic)Text).color = new Color(0f, 0.75f, 1f, 1f);
			((TMP_Text)Text).fontSize = 18f;
			base.showPosition = new Vector2(-330f, 120f);
			base.hidePosition = new Vector2(-430f, 120f);
			levelTimerElapsedTime = 0f;
		}

		protected override void Update()
		{
			((SemiUI)this).Update();
			if (!TimerPlugin_Config.configLevelTimerEnabled.Value)
			{
				((SemiUI)this).Hide();
				return;
			}
			levelTimerElapsedTime += Time.deltaTime;
			if (setup)
			{
				if (LevelGenerator.Instance.Generated)
				{
					setup = false;
				}
			}
			else if (!((Object)(object)Text == (Object)null))
			{
				int num = Mathf.FloorToInt(levelTimerElapsedTime / 60f);
				int num2 = Mathf.FloorToInt(levelTimerElapsedTime % 60f);
				((TMP_Text)Text).text = $"{num:00}:{num2:00}";
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "GenerateDone")]
	public class LevelGenerator_GenerateDone_Patcher
	{
		private static void CreateFromHealth<T>(string objectName) where T : SemiUI
		{
			GameObject val = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud");
			GameObject val2 = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud/Health");
			GameObject val3 = Object.Instantiate<GameObject>(val2, val.transform);
			Object.Destroy((Object)(object)val3.GetComponent<HealthUI>());
			Transform[] array = ((IEnumerable)val3.transform).Cast<Transform>().ToArray();
			foreach (Transform val4 in array)
			{
				Object.DestroyImmediate((Object)(object)((Component)val4).gameObject, true);
			}
			((Object)val3).name = objectName;
			val3.AddComponent<T>();
		}

		private static void CreateTimers()
		{
			GameObject val = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud");
			GameObject val2 = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud/Health");
			GameObject val3 = Object.Instantiate<GameObject>(val2, val.transform);
			GameObject val4 = Object.Instantiate<GameObject>(val2, val.transform);
			Object.Destroy((Object)(object)val3.GetComponent<HealthUI>());
			Object.Destroy((Object)(object)val4.GetComponent<HealthUI>());
			Transform[] array = ((IEnumerable)val3.transform).Cast<Transform>().ToArray();
			foreach (Transform val5 in array)
			{
				Object.DestroyImmediate((Object)(object)((Component)val5).gameObject, true);
			}
			Transform[] array2 = ((IEnumerable)val4.transform).Cast<Transform>().ToArray();
			foreach (Transform val6 in array2)
			{
				Object.DestroyImmediate((Object)(object)((Component)val6).gameObject, true);
			}
			((Object)val3).name = "LevelTimer";
			val3.AddComponent<LevelTimerUI>();
			((Object)val4).name = "IdleCountdown";
			val4.AddComponent<IdleCountdownUI>();
		}

		private static void CreateEnemyList()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud");
			GameObject val2 = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud/Stats");
			GameObject val3 = Object.Instantiate<GameObject>(val2, val.transform);
			((Object)val3).name = "EnemyList";
			Transform val4 = val3.transform.Find("StatsNumbers");
			Transform val5 = val3.transform.Find("Upgrades Header");
			((Object)val4).name = "RespawnTimes";
			val4.localPosition = new Vector3(100f, -25f, 0f);
			((Component)val4).GetComponent<RectTransform>().sizeDelta = new Vector2(100f, 62f);
			((Object)val5).name = "Enemies Header";
			val5.localPosition = new Vector3(-30f, 60f, 0f);
			EnemyListUI enemyListUI = val3.AddComponent<EnemyListUI>();
			StatsUI component = val3.GetComponent<StatsUI>();
			enemyListUI.scanlineObject = ((Component)component).GetComponent<StatsUI>()?.scanlineObject;
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
		}

		private static void Postfix()
		{
			try
			{
				if (Enumerable.Contains(RunManager.instance.levels, RunManager.instance.levelCurrent))
				{
					if (TimerPlugin_Config.configLevelTimerEnabled.Value)
					{
						CreateFromHealth<LevelTimerUI>("LevelTimer");
					}
					if (TimerPlugin_Config.configIdleCountdownEnabled.Value)
					{
						CreateFromHealth<IdleCountdownUI>("IdleCountdown");
					}
					if (TimerPlugin_Config.configEnemyTimerEnabled.Value)
					{
						CreateEnemyList();
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Exception in LevelGenerator.GenerateDone patch:\n{arg}");
			}
		}
	}
	[HarmonyPatch(typeof(MapToolController), "Update")]
	public class MapToolController_Update_Patch
	{
		private static FieldRef<MapToolController, PhotonView> photonViewRef = AccessTools.FieldRefAccess<MapToolController, PhotonView>("photonView");

		private static FieldRef<MapToolController, bool> activeRef = AccessTools.FieldRefAccess<MapToolController, bool>("Active");

		private static void Postfix(MapToolController __instance)
		{
			if ((!GameManager.Multiplayer() || photonViewRef.Invoke(__instance).IsMine) && activeRef.Invoke(__instance) && (Object)(object)EnemyListUI.instance != (Object)null)
			{
				((SemiUI)EnemyListUI.instance).Show();
			}
		}
	}
	[HarmonyPatch(typeof(MenuPage), "LockAndHide")]
	public class MenuPage_LockAndHide_Patch
	{
		private static void Postfix()
		{
			if ((Object)(object)LevelTimerUI.instance != (Object)null && (Object)(object)IdleCountdownUI.instance != (Object)null)
			{
				((SemiUI)LevelTimerUI.instance).Hide();
				((SemiUI)IdleCountdownUI.instance).Hide();
			}
		}
	}
	[HarmonyPatch(typeof(EnemyParent), "SpawnRPC")]
	public class EnemyParent_SpawnRPC_Patch
	{
		private static void Postfix(EnemyParent __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (TimerPlugin_Config.configEnemyTimerEnabled.Value && Object.op_Implicit((Object)(object)EnemyListUI.instance))
			{
				EnemyListUI.instance.BigMessage(__instance.enemyName, __instance.difficulty);
			}
		}
	}
	[BepInPlugin("TimerPlugin", "Timer Plugin", "1.1.1")]
	[BepInProcess("REPO.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Logger;

		public TimerPlugin_Config ConfigInstance;

		private static Harmony _harmony = new Harmony("TimerPlugin");

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			ConfigInstance = new TimerPlugin_Config(((BaseUnityPlugin)this).Config);
			ConfigInstance.RegisterOptions();
			if (TimerPlugin_Config.configPluginEnabled.Value)
			{
				_harmony.PatchAll();
				Logger.LogInfo((object)"Plugin Loaded");
			}
			else
			{
				Logger.LogWarning((object)"Plugin disabled in config");
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "TimerPlugin";

		public const string PLUGIN_NAME = "Timer Plugin";

		public const string PLUGIN_VERSION = "1.1.1";
	}
}