Decompiled source of TellMeMobs v1.2.0

TellMeMobs.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("McHorse")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+cb716749d5fcf1a12f83d8633ad3742bb0520f76")]
[assembly: AssemblyProduct("TellMeMobs")]
[assembly: AssemblyTitle("TellMeMobs")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 TellMeMobs
{
	[HarmonyPatch(typeof(RoundDirector))]
	public static class RoundDirectorPatch
	{
		public static GameObject? textObject;

		public static TextMeshProUGUI? textMesh;

		private static float _nextUpdateTime;

		private static readonly float[] Sizes = new float[4] { 24f, 18f, 14f, 11f };

		private static readonly FieldInfo MapToggledField = AccessTools.Field(typeof(MapToolController), "mapToggled");

		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		public static void UpdateUI()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.RunIsLevel())
			{
				return;
			}
			if ((Object)(object)textObject == (Object)null)
			{
				GameObject val = GameObject.Find("Game Hud");
				GameObject val2 = GameObject.Find("Tax Haul");
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
				{
					textObject = new GameObject();
					textObject.SetActive(false);
					((Object)textObject).name = "Mob Info";
					textObject.AddComponent<TextMeshProUGUI>();
					textObject.transform.SetParent(val.transform, false);
					ContentSizeFitter val3 = textObject.AddComponent<ContentSizeFitter>();
					val3.verticalFit = (FitMode)2;
					val3.horizontalFit = (FitMode)0;
					textMesh = textObject.GetComponent<TextMeshProUGUI>();
					((TMP_Text)textMesh).font = val2.GetComponent<TMP_Text>().font;
					((Graphic)textMesh).color = Color.op_Implicit(new Vector4(1f, 1f, 1f, 1f));
					((TMP_Text)textMesh).fontSize = 24f;
					((TMP_Text)textMesh).enableWordWrapping = false;
					((TMP_Text)textMesh).alignment = (TextAlignmentOptions)2052;
					((TMP_Text)textMesh).horizontalAlignment = (HorizontalAlignmentOptions)4;
					((TMP_Text)textMesh).verticalAlignment = (VerticalAlignmentOptions)1024;
					RectTransform component = textObject.GetComponent<RectTransform>();
					component.pivot = new Vector2(1f, 0f);
					component.anchoredPosition = new Vector2(0f, 0f);
					component.anchorMin = new Vector2(0f, 0f);
					component.anchorMax = new Vector2(1f, 0f);
				}
			}
			else
			{
				if (!((Object)(object)textMesh != (Object)null))
				{
					return;
				}
				float time = Time.time;
				if (!(time < _nextUpdateTime))
				{
					_nextUpdateTime = time + 0.25f;
					List<MobEntry> entries = TellMeMobsUtils.CollectMobEntries();
					string text = TellMeMobsUtils.JoinMobPlain(entries);
					bool flag = text.Length > 0;
					MobLabelVisibility value = TellMeMobs.LabelVisibility.Value;
					bool flag2 = SemiFunc.InputHold((InputKey)8) || ((Object)(object)MapToolController.instance != (Object)null && (bool)MapToggledField.GetValue(MapToolController.instance));
					bool active = flag && (value == MobLabelVisibility.Visible || (value == MobLabelVisibility.MapVisible && flag2));
					textObject.SetActive(active);
					if (flag)
					{
						int num = Mathf.Clamp((text.Length - 1) / 48, 0, 3);
						float num2 = Sizes[num];
						string text2 = TellMeMobsUtils.JoinMobRich(entries);
						((TMP_Text)textMesh).SetText(text2, true);
						((TMP_Text)textMesh).fontSize = num2;
						((TMP_Text)textMesh).lineSpacing = (0f - num2) * 1.5f;
					}
				}
			}
		}
	}
	public enum MobLabelVisibility
	{
		Invisible,
		MapVisible,
		Visible
	}
	[BepInPlugin("McHorse.TellMeMobs", "TellMeMobs", "1.2")]
	public class TellMeMobs : BaseUnityPlugin
	{
		private bool _postedMessage;

		private bool _wasntTyping;

		internal static TellMeMobs Instance { get; private set; }

		internal static ConfigEntry<MobLabelVisibility> LabelVisibility { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		public static string GetMobInformation()
		{
			return TellMeMobsUtils.JoinMobPlain(TellMeMobsUtils.CollectMobEntries());
		}

		private void Awake()
		{
			Instance = this;
			LabelVisibility = ((BaseUnityPlugin)this).Config.Bind<MobLabelVisibility>("General", "Label visibility", MobLabelVisibility.Invisible, "When to show the mob list on the HUD: never visible, visible when map opened, and always visible");
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

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

		private void Update()
		{
			if (!SemiFunc.LevelGenDone())
			{
				_postedMessage = false;
				_wasntTyping = false;
			}
			else
			{
				if (_postedMessage || Time.timeSinceLevelLoad < 10f)
				{
					return;
				}
				TruckScreenText instance = TruckScreenText.instance;
				if (!Object.op_Implicit((Object)(object)instance))
				{
					return;
				}
				if (!_wasntTyping)
				{
					if (!instance.isTyping)
					{
						return;
					}
					_wasntTyping = true;
				}
				if (!instance.isTyping)
				{
					string mobInformation = GetMobInformation();
					if (mobInformation.Length > 0)
					{
						TextMeshProUGUI textMesh = instance.textMesh;
						((TMP_Text)textMesh).text = ((TMP_Text)textMesh).text + "\n\n<color=#4d0000><b>TAXMAN:</b></color>\n<sprite name=heart> " + mobInformation;
					}
					_postedMessage = true;
				}
			}
		}
	}
	public static class TellMeMobsUtils
	{
		private static readonly Dictionary<string, (int Total, int Kills, int Despawned)> _map = new Dictionary<string, (int, int, int)>();

		private static readonly List<MobEntry> _entries = new List<MobEntry>();

		public static List<MobEntry> CollectMobEntries()
		{
			_map.Clear();
			_entries.Clear();
			EnemyDirector instance = EnemyDirector.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return _entries;
			}
			List<EnemyParent> enemiesSpawned = instance.enemiesSpawned;
			for (int i = 0; i < enemiesSpawned.Count; i++)
			{
				EnemyParent val = enemiesSpawned[i];
				if (!((Object)(object)val == (Object)null))
				{
					string enemyName = val.enemyName;
					(int Total, int Kills, int Despawned) valueOrDefault = _map.GetValueOrDefault(enemyName, (0, 0, 0));
					int item = valueOrDefault.Total;
					int num = valueOrDefault.Kills;
					int num2 = valueOrDefault.Despawned;
					item++;
					if (IsEnemyKilled(val))
					{
						num++;
					}
					else if (!val.Spawned)
					{
						num2++;
					}
					_map[enemyName] = (item, num, num2);
				}
			}
			foreach (KeyValuePair<string, (int, int, int)> item3 in _map)
			{
				string text = item3.Key.ToUpper();
				int item2 = item3.Value.Item1;
				string label = ((item2 == 1) ? text : $"{text}x{item2}");
				_entries.Add(new MobEntry(label, item3.Value.Item2, item3.Value.Item3, item2));
			}
			_entries.Sort((MobEntry a, MobEntry b) => string.Compare(a.Label, b.Label, StringComparison.Ordinal));
			return _entries;
		}

		private static bool IsEnemyKilled(EnemyParent enemy)
		{
			if ((Object)(object)enemy.Enemy == (Object)null || !enemy.Enemy.HasHealth)
			{
				return false;
			}
			EnemyHealth health = enemy.Enemy.Health;
			return health.healthCurrent <= 0 || health.dead;
		}

		public static string JoinMobPlain(IReadOnlyList<MobEntry> entries)
		{
			if (entries.Count == 0)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < entries.Count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(entries[i].Label);
			}
			return stringBuilder.ToString();
		}

		public static string JoinMobRich(IReadOnlyList<MobEntry> entries, int lineLength = 48)
		{
			if (entries.Count == 0)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			for (int i = 0; i < entries.Count; i++)
			{
				MobEntry entry = entries[i];
				string value = FormatMobEntryRich(entry);
				int length = entry.Label.Length;
				if (i == 0)
				{
					stringBuilder.Append(value);
					num = length;
				}
				else if (num + ", ".Length + length > lineLength)
				{
					stringBuilder.Append(",\n");
					stringBuilder.Append(value);
					num = length;
				}
				else
				{
					stringBuilder.Append(", ");
					stringBuilder.Append(value);
					num += ", ".Length + length;
				}
			}
			return stringBuilder.ToString();
		}

		private static string FormatMobEntryRich(MobEntry entry)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0064: 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)
			float num = ((entry.Total > 0) ? ((float)entry.Killed / (float)entry.Total) : 0f);
			float num2 = ((entry.Total > 0) ? ((float)entry.Despawned / (float)entry.Total) : 0f);
			Color val = Color.Lerp(Color.white, Color.red, num);
			val = Color.Lerp(val, Color.yellow, num2);
			string text = ColorUtility.ToHtmlStringRGB(val);
			return "<color=#" + text + ">" + entry.Label + "</color>";
		}
	}
	public readonly struct MobEntry
	{
		public string Label { get; }

		public int Killed { get; }

		public int Despawned { get; }

		public int Total { get; }

		public MobEntry(string label, int killed, int despawned, int total)
		{
			Label = label;
			Killed = killed;
			Despawned = despawned;
			Total = total;
		}
	}
}