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 value = Traverse.Create((object)__instance).Field>("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 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(); 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? list) { if (list == null) { Plugin.Log.LogInfo((object)(label + ": ")); 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 : ""))); } } 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.renderMode = (RenderMode)0; _canvas.sortingOrder = 32767; _canvas.overrideSorting = true; CanvasScaler obj = val.AddComponent(); obj.uiScaleMode = (ScaleMode)0; obj.scaleFactor = 1f; val.AddComponent(); _bgGameObject = new GameObject("Background"); _bgGameObject.transform.SetParent(val.transform, false); _bgGameObject.layer = 5; Image obj2 = _bgGameObject.AddComponent(); ((Graphic)obj2).color = new Color(0f, 0f, 0f, 0.75f); ((Graphic)obj2).raycastTarget = false; RectTransform component = _bgGameObject.GetComponent(); 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.font = Resources.GetBuiltinResource("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(); 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().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 DisableLoom; internal static ConfigEntry ShowBossBanner; internal static ConfigEntry 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("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("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("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(); } } } [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() != (Object)null)) { ((Component)__instance).gameObject.AddComponent(); Plugin.Log.LogInfo((object)"BannerRpcHandler attached to PunManager."); } } } }