Decompiled source of BossNotifier v1.0.7

plugins/BossNotifier/BossNotifier.dll

Decompiled a day 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BossNotifier")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyInformationalVersion("1.0.7")]
[assembly: AssemblyProduct("BossNotifier")]
[assembly: AssemblyTitle("BossNotifier")]
[assembly: AssemblyVersion("1.0.7.0")]
[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 BossNotifier
{
	[HarmonyPatch(typeof(EnemyDirector), "AmountSetup")]
	[HarmonyWrapSafe]
	public static class AmountSetupPatch
	{
		public static string? PendingMessage;

		private static bool _hasLoggedNames;

		[HarmonyPrefix]
		public static void Prefix(EnemyDirector __instance)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			if (!_hasLoggedNames)
			{
				_hasLoggedNames = true;
				LogTier("Tier 1", __instance.enemiesDifficulty1);
				LogTier("Tier 2", __instance.enemiesDifficulty2);
				LogTier("Tier 3", __instance.enemiesDifficulty3);
			}
			if (Plugin.DisableLoom.Value && __instance.enemiesDifficulty3 != null)
			{
				int num = __instance.enemiesDifficulty3.RemoveAll((EnemySetup setup) => (Object)(object)setup != (Object)null && !string.IsNullOrEmpty(((Object)setup).name) && ((Object)setup).name.IndexOf("Shadow", StringComparison.OrdinalIgnoreCase) >= 0);
				if (num > 0)
				{
					Plugin.Log.LogInfo((object)$"Loom Toggle: removed {num} Loom (Shadow) entries from tier-3 pool.");
				}
			}
		}

		[HarmonyPostfix]
		public static void Postfix(EnemyDirector __instance)
		{
			if (!PhotonNetwork.IsMasterClient || !Plugin.ShowBossBanner.Value)
			{
				return;
			}
			List<EnemySetup> value = Traverse.Create((object)__instance).Field<List<EnemySetup>>("enemyList").Value;
			if (value == null || value.Count == 0)
			{
				return;
			}
			var list = (from e in value
				where (Object)(object)e != (Object)null && !string.IsNullOrEmpty(((Object)e).name)
				group e by PrettifyName(((Object)e).name) into g
				select new
				{
					Name = g.Key,
					Count = g.Count()
				} into x
				orderby x.Count descending, x.Name
				select x).ToList();
			if (list.Count == 0)
			{
				return;
			}
			List<string> values = list.Select(x => (x.Count != 1) ? $"{x.Count} {Pluralize(x.Name)} Spawned" : (x.Name + " Spawned")).ToList();
			string text = (PendingMessage = string.Join("\n", values));
			Plugin.Log.LogInfo((object)("Spawn message queued (host): " + string.Join(", ", values)));
			if ((Object)(object)PunManager.instance != (Object)null)
			{
				PhotonView component = ((Component)PunManager.instance).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					component.RPC("ReceiveBannerMessage", (RpcTarget)1, new object[1] { text });
					Plugin.Log.LogInfo((object)"Banner RPC sent to clients.");
				}
				else
				{
					Plugin.Log.LogWarning((object)"PunManager has no PhotonView; clients won't receive banner.");
				}
			}
			else
			{
				Plugin.Log.LogWarning((object)"PunManager.instance is null; can't broadcast banner.");
			}
		}

		private static void LogTier(string label, List<EnemySetup>? list)
		{
			if (list == null)
			{
				Plugin.Log.LogInfo((object)(label + ": <null>"));
				return;
			}
			Plugin.Log.LogInfo((object)$"{label} ({list.Count} entries):");
			foreach (EnemySetup item in list)
			{
				Plugin.Log.LogInfo((object)("  - " + (((Object)(object)item != (Object)null) ? ((Object)item).name : "<null setup>")));
			}
		}

		private static string PrettifyName(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return "Unknown";
			}
			string text = raw;
			int num = text.LastIndexOf('-');
			if (num >= 0 && num < text.Length - 1)
			{
				text = text.Substring(num + 1).Trim();
			}
			if (text.StartsWith("Enemy ", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(6).Trim();
			}
			if (text == "Shadow")
			{
				return "Loom";
			}
			return text;
		}

		private static string Pluralize(string name)
		{
			if (!(name == "Headman"))
			{
				if (name == "Huntsman")
				{
					return "Huntsmen";
				}
				if (name.EndsWith("man", StringComparison.OrdinalIgnoreCase))
				{
					return name.Substring(0, name.Length - 3) + "men";
				}
				if (name.EndsWith("y", StringComparison.OrdinalIgnoreCase) && name.Length >= 2)
				{
					char value = name[name.Length - 2];
					if (!"aeiouAEIOU".Contains(value))
					{
						return name.Substring(0, name.Length - 1) + "ies";
					}
				}
				if (name.EndsWith("s", StringComparison.OrdinalIgnoreCase) || name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("z", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase))
				{
					return name + "es";
				}
				return name + "s";
			}
			return "Headmen";
		}
	}
	public class BannerRpcHandler : MonoBehaviour
	{
		public static BannerRpcHandler? Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
			}
			else
			{
				Instance = this;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		[PunRPC]
		public void ReceiveBannerMessage(string message)
		{
			Plugin.Log.LogInfo((object)("Received banner message via RPC: " + message.Replace('\n', '|')));
			AmountSetupPatch.PendingMessage = message;
		}
	}
	public class BossBanner : MonoBehaviour
	{
		private Canvas? _canvas;

		private Text? _text;

		private GameObject? _bgGameObject;

		private float _hideAt;

		public static BossBanner? Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			BuildCanvas();
		}

		private void BuildCanvas()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("BossNotifier_Canvas");
			val.transform.SetParent(((Component)this).transform, false);
			val.layer = 5;
			_canvas = val.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 32767;
			_canvas.overrideSorting = true;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)0;
			obj.scaleFactor = 1f;
			val.AddComponent<GraphicRaycaster>();
			_bgGameObject = new GameObject("Background");
			_bgGameObject.transform.SetParent(val.transform, false);
			_bgGameObject.layer = 5;
			Image obj2 = _bgGameObject.AddComponent<Image>();
			((Graphic)obj2).color = new Color(0f, 0f, 0f, 0.75f);
			((Graphic)obj2).raycastTarget = false;
			RectTransform component = _bgGameObject.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 1f);
			component.anchorMax = new Vector2(0.5f, 1f);
			component.pivot = new Vector2(0.5f, 1f);
			component.anchoredPosition = new Vector2(0f, -80f);
			component.sizeDelta = new Vector2(600f, 150f);
			GameObject val2 = new GameObject("Text");
			val2.transform.SetParent(_bgGameObject.transform, false);
			val2.layer = 5;
			_text = val2.AddComponent<Text>();
			_text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			_text.fontSize = 28;
			_text.fontStyle = (FontStyle)1;
			_text.alignment = (TextAnchor)4;
			((Graphic)_text).color = Color.white;
			_text.text = "";
			((Graphic)_text).raycastTarget = false;
			RectTransform component2 = ((Component)_text).GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = new Vector2(20f, 16f);
			component2.offsetMax = new Vector2(-20f, -16f);
			_bgGameObject.SetActive(false);
		}

		public void Show(string message, float seconds)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_text == (Object)null) && !((Object)(object)_bgGameObject == (Object)null))
			{
				_text.text = message;
				int num = message.Split('\n').Length;
				float num2 = Mathf.Max(80f, 36f * (float)num + 32f);
				_bgGameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(600f, num2);
				_hideAt = Time.unscaledTime + seconds;
				_bgGameObject.SetActive(true);
			}
		}

		private void Update()
		{
			if ((Object)(object)_bgGameObject != (Object)null && _bgGameObject.activeSelf && Time.unscaledTime > _hideAt)
			{
				_bgGameObject.SetActive(false);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "LoadingLevelAnimationCompletedRPC")]
	[HarmonyWrapSafe]
	public static class LoadingCompletePatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		public static void Postfix(PlayerAvatar __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			PhotonView photonView = __instance.photonView;
			if (!((Object)(object)photonView == (Object)null) && photonView.IsMine && !string.IsNullOrEmpty(AmountSetupPatch.PendingMessage))
			{
				string pendingMessage = AmountSetupPatch.PendingMessage;
				AmountSetupPatch.PendingMessage = null;
				if (!((Object)(object)BossBanner.Instance == (Object)null))
				{
					BossBanner.Instance.Show(pendingMessage, Plugin.BannerDurationSeconds.Value);
				}
			}
		}
	}
	internal static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.deegamenchill.bossnotifier";

		public const string PLUGIN_NAME = "BossNotifier";

		public const string PLUGIN_VERSION = "1.0.7";
	}
	[BepInPlugin("com.deegamenchill.bossnotifier", "BossNotifier", "1.0.7")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> DisableLoom;

		internal static ConfigEntry<bool> ShowBossBanner;

		internal static ConfigEntry<float> BannerDurationSeconds;

		private void Awake()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			DisableLoom = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "DisableLoom", false, "If true (and you are the host), Loom will be removed from the spawn pool. Has no effect on non-host clients.");
			ShowBossBanner = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowSpawnBanner", true, "Show an on-screen banner at the start of each level listing every enemy that will spawn (with counts: e.g. \"2 Ducks Spawned\").");
			BannerDurationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "BannerDurationSeconds", 6f, "How long the spawn banner stays on screen.");
			new Harmony("com.deegamenchill.bossnotifier").PatchAll();
			SceneManager.sceneLoaded += OnSceneLoaded;
			Log.LogInfo((object)"com.deegamenchill.bossnotifier v1.0.7 loaded.");
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)BossBanner.Instance != (Object)null))
			{
				GameObject val = new GameObject("BossNotifier_Host");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<BossBanner>();
			}
		}
	}
	[HarmonyPatch(typeof(PunManager), "Start")]
	[HarmonyWrapSafe]
	public static class PunManagerInitPatch
	{
		[HarmonyPostfix]
		public static void Postfix(PunManager __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).gameObject.GetComponent<BannerRpcHandler>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<BannerRpcHandler>();
				Plugin.Log.LogInfo((object)"BannerRpcHandler attached to PunManager.");
			}
		}
	}
}