Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SpectatorChat v1.1.8
SpectatorChat.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using OPJosMod.ReviveCompany; using OPJosMod.ReviveCompany.CustomRpc; using ReservedItemSlotCore.Patches; using SpectatorChat.API; using SpectatorChat.Other; using SpectatorChat.Patch.Chat; using SpectatorChat.Patch.HUD; using SpectatorChat.Patch.Other; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Build")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("5.0.1")] [assembly: AssemblyInformationalVersion("3.0.0")] [assembly: AssemblyProduct("SpectatorChat")] [assembly: AssemblyTitle("SpectatorChat")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.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 SpectatorChat { [BepInPlugin("Kaguya.SpectatorChat", "SpectatorChat", "1.1.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public class InputKey : LcInputActions { [InputAction("<Keyboard>/r", Name = "ToggleDeathBox")] public InputAction ToggleDeathBoxKey { get; set; } } private const string ModGuid = "Kaguya.SpectatorChat"; private const string ModName = "SpectatorChat"; private const string ModVersion = "1.1.8"; private static readonly List<string> ModId = new List<string>(); private readonly Harmony _harmony = new Harmony("Kaguya.SpectatorChat"); private static Plugin Instance; public static ManualLogSource mls; internal static InputKey InputActionInstance = new InputKey(); public static ConfigEntry<bool> ShowClock { get; private set; } public static ConfigEntry<bool> CanLivingPlayerReceiveMessage { get; private set; } public static ConfigEntry<float> CoroutineDelay { get; private set; } public static bool KeyPressed { get; set; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } mls = Logger.CreateLogSource("Kaguya.SpectatorChat"); mls.LogInfo((object)"SpectatorChat has loaded."); LoadConfigs(); PatchAll(); LogPatchInfo(); } private void LoadSpecificPatch() { ModId.Add("OpJosMod.ReviveCompany"); ModId.Add("FlipMods.ReservedItemSlotCore"); ((MonoBehaviour)this).StartCoroutine(WaitForDependentMod()); } private IEnumerator WaitForDependentMod() { float startTime = Time.time; float timeout = 120f; if (!GlobalVariables.Init) { GlobalVariables.Init = true; while (Time.time - startTime <= timeout) { Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos; int num = 0; foreach (string key in pluginInfos.Keys) { if (key == "OpJosMod.ReviveCompany") { _harmony.PatchAll(typeof(ReviveCompanyPatch)); num++; mls.LogInfo((object)("Detected " + key + ", Proceeding PostPatch...")); } else if (key == "FlipMods.ReservedItemSlotCore") { GlobalVariables.InitReservedItem = true; num++; mls.LogInfo((object)("Detected " + key + ", Proceeding...")); } } mls.LogInfo((object)$"Mod found. Totally {num} Extra method were executed."); yield return (object)new WaitForSeconds(10f); } } mls.LogInfo((object)"Timeout reached or canceled."); } private void PatchAll() { _harmony.PatchAll(typeof(EnableChatPatch)); _harmony.PatchAll(typeof(SubmitChatPatch)); _harmony.PatchAll(typeof(HUDPatch)); _harmony.PatchAll(typeof(AddPlayerChatMessagePatch)); _harmony.PatchAll(typeof(HUDManagerPostfixPatch)); _harmony.PatchAll(typeof(KillPlayerPostfixPatch)); _harmony.PatchAll(typeof(HideHUDPostfixPatch)); _harmony.PatchAll(typeof(SetShipReadyToLandPostfix)); _harmony.PatchAll(typeof(KeyPatch)); LoadSpecificPatch(); } private void LoadConfigs() { ShowClock = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ShowClock", true, "Show the clock for spectator players."); CanLivingPlayerReceiveMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "CanLivingPlayerReceiveMessage", false, "Can living player receive dead player's message."); CoroutineDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "CoroutineDelay", 1f, "How long will the coroutine delay."); mls.LogInfo((object)$"Plugin loaded with config: ShowClock: {ShowClock.Value}, CanLivingPlayerReceiveMessage: {CanLivingPlayerReceiveMessage.Value}, CoroutineDelay: {CoroutineDelay.Value}"); } private void LogPatchInfo() { mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(HUDManager), "Awake", (Type[])null, (Type[])null))); mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(HUDManager), "EnableChat_performed", (Type[])null, (Type[])null))); mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(HUDManager), "SubmitChat_performed", (Type[])null, (Type[])null))); mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(PlayerControllerB), "KillPlayer", (Type[])null, (Type[])null))); mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(PlayerControllerB), "Update", (Type[])null, (Type[])null))); mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(HUDManager), "HideHUD", (Type[])null, (Type[])null))); mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(StartOfRound), "SetShipReadyToLand", (Type[])null, (Type[])null))); mls.LogInfo((object)HarmonyAPI.GetPatchInfoAsString(_harmony, AccessTools.Method(typeof(CompleteRecievedTasks), "RevivePlayer", (Type[])null, (Type[])null))); } } } namespace SpectatorChat.Patch.Other { internal static class HideHUDPostfixPatch { [HarmonyPatch(typeof(HUDManager), "HideHUD")] private static void Postfix(HUDManager __instance) { HarmonyAPI.LogCallingMethod("HideHUD"); if (Generic.Instance.IsCoroutineNull()) { return; } try { if (Generic.Instance.StopPermanentTransparent()) { Plugin.mls.LogInfo((object)("Routine stopped successfully. Player " + GlobalVariables.PlayerControllerInstance.playerUsername)); } else { Plugin.mls.LogInfo((object)("Routine stopped failed. Player " + GlobalVariables.PlayerControllerInstance.playerUsername)); } } catch (Exception ex) { Plugin.mls.LogError((object)(ex.StackTrace + ex.Message)); throw; } } } internal static class KillPlayerPostfixPatch { [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] private static void Postfix(PlayerControllerB __instance) { HarmonyAPI.LogCallingMethod("KillPlayer"); if (((NetworkBehaviour)__instance).IsOwner && Generic.Instance.StartPermanentTransparent()) { GlobalVariables.PlayerControllerInstance.bleedingHeavily = false; GlobalVariables.PlayerControllerInstance.criticallyInjured = false; HUDManager.Instance.HUDAnimator.SetTrigger("revealHud"); Plugin.mls.LogInfo((object)("Routine start successfully. Player " + __instance.playerUsername)); } } } internal static class ReviveCompanyPatch { [HarmonyPatch(typeof(CompleteRecievedTasks), "RevivePlayer")] private static bool Prefix(ref string playerIdString) { HarmonyAPI.LogCallingMethod("RevivePlayer"); if (int.TryParse(playerIdString, out var result)) { GeneralUtil.RevivePlayer(result); if (Generic.IsInstanceOwner(playerIdString)) { Plugin.mls.LogInfo((object)$"Player {GlobalVariables.PlayerControllerInstance.playerUsername} has been revived and IsInstanceOwner: {Generic.IsInstanceOwner(playerIdString)}"); Generic.ClearSpectatorUI(GlobalVariables.HUDManagerInstance); if (Generic.Instance.StopPermanentTransparent()) { Plugin.mls.LogInfo((object)("Routine stopped successfully. Player " + GlobalVariables.PlayerControllerInstance.playerUsername)); } else { Plugin.mls.LogInfo((object)("Routine stopped failed. Player " + GlobalVariables.PlayerControllerInstance.playerUsername)); } } } else { Plugin.mls.LogError((object)("Error: Invalid player ID '" + playerIdString + "' did not revive")); } return false; } } } namespace SpectatorChat.Patch.HUD { [HarmonyPatch(typeof(HUDManager), "Awake")] internal static class HUDManagerPostfixPatch { private static void Postfix(HUDManager __instance) { HUDManager __instance2 = __instance; HarmonyAPI.LogCallingMethod("HUDManager.Awake"); GlobalVariables.HUDManagerInstance = __instance2; if (GlobalVariables.InitReservedItem) { ReservedItemUI.InitReservedItemUI(); } if (Plugin.ShowClock.Value) { GlobalVariables.HUDElements = __instance2.HUDElements.Where((HUDElement element) => element != __instance2.HUDElements[1] && element != __instance2.HUDElements[5]).ToArray(); } else { GlobalVariables.HUDElements = __instance2.HUDElements.Where((HUDElement element) => element != __instance2.HUDElements[1]).ToArray(); } } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] internal static class HUDPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { HarmonyAPI.LogCallingMethod("KillPlayer"); List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo hideHUDMethod = typeof(HUDManager).GetMethod("HideHUD"); Plugin.mls.LogInfo((object)"Processing KillPlayer method..."); int num; try { num = list.FindLastIndex((CodeInstruction i) => i.opcode == OpCodes.Callvirt && i.operand is MethodInfo methodInfo && methodInfo.Equals(hideHUDMethod)); Plugin.mls.LogInfo((object)$"Index: {num} Code: {list[num]} found."); num -= 2; } catch (Exception ex) { Plugin.mls.LogError((object)(ex.Message + ex.StackTrace)); throw; } try { Plugin.mls.LogInfo((object)"Patching following codes..."); for (int j = 0; j <= 2; j++) { Plugin.mls.LogInfo((object)$"Index: {num + j}, Code: {list[num + j]}"); list[num + j].opcode = OpCodes.Nop; } Plugin.mls.LogInfo((object)"Patched codes:"); for (int k = 0; k <= 2; k++) { Plugin.mls.LogInfo((object)$"Index: {num + k}, Code: {list[num + k]}"); } } catch (Exception ex2) { Plugin.mls.LogError((object)(ex2.Message + ex2.StackTrace)); throw; } finally { Plugin.mls.LogInfo((object)"Patch success. No any fatal error were raised."); } foreach (CodeInstruction item in list) { yield return item; } } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] internal static class KeyPatch { internal static void Postfix(PlayerControllerB __instance) { if ((!((NetworkBehaviour)__instance).IsOwner || (!__instance.isPlayerControlled && !__instance.isPlayerDead) || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject)) && !__instance.isTestingPlayer) { return; } if ((Object)(object)GlobalVariables.PlayerControllerInstance != (Object)(object)__instance || (Object)(object)GlobalVariables.PlayerControllerInstance == (Object)null) { Plugin.mls.LogInfo((object)$"Player instance has changed due to {(Object)(object)GlobalVariables.PlayerControllerInstance != (Object)(object)__instance} or {(Object)(object)GlobalVariables.PlayerControllerInstance == (Object)null}"); GlobalVariables.PlayerControllerInstance = __instance; } if (__instance.isPlayerDead && Plugin.InputActionInstance.ToggleDeathBoxKey.WasPressedThisFrame()) { if (!Plugin.KeyPressed) { Generic.ToggleSpectatorBoxUI(GlobalVariables.HUDManagerInstance, isVisable: false); Plugin.KeyPressed = true; } else { Generic.ToggleSpectatorBoxUI(GlobalVariables.HUDManagerInstance, isVisable: true); Plugin.KeyPressed = false; } } } } [HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")] internal static class SetShipReadyToLandPostfix { private static void Postfix() { HarmonyAPI.LogCallingMethod("StartOfRound.SetShipReadyToLand"); Generic.ClearSpectatorUI(GlobalVariables.HUDManagerInstance); } } } namespace SpectatorChat.Patch.Chat { [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageClientRpc")] internal static class AddPlayerChatMessagePatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { HarmonyAPI.LogCallingMethod("AddPlayerChatMessageClientRpc"); List<CodeInstruction> list = new List<CodeInstruction>(instructions); Label label = generator.DefineLabel(); FieldInfo targetField = typeof(PlayerControllerB).GetField("isPlayerDead"); Plugin.mls.LogInfo((object)"Processing AddPlayerChatMessageClientRpc method..."); int num; try { num = list.FindLastIndex((CodeInstruction instruction) => instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo fieldInfo && fieldInfo.Equals(targetField)); Plugin.mls.LogInfo((object)$"Index: {num} Code: {list[num]} found."); num -= 9; Plugin.mls.LogInfo((object)$"Got previous IL Code: {list[num]}."); } catch (Exception ex) { Plugin.mls.LogError((object)(ex.Message + ex.StackTrace)); throw; } try { Plugin.mls.LogInfo((object)"Patching following codes..."); for (int i = 0; i <= 11; i++) { Plugin.mls.LogInfo((object)$"Index: {num + i}, Code: {list[num + i]}"); list[num + i].opcode = OpCodes.Nop; } Plugin.mls.LogInfo((object)"Patched codes:"); for (int j = 0; j <= 11; j++) { Plugin.mls.LogInfo((object)$"Index: {num + j}, Code: {list[num + j]}"); } } catch (Exception ex2) { Plugin.mls.LogError((object)(ex2.Message + ex2.StackTrace)); throw; } finally { Plugin.mls.LogInfo((object)"Patch success. No any fatal error were raised."); } Plugin.mls.LogInfo((object)"Now processing patch 2..."); try { num = list.FindLastIndex((CodeInstruction instruction) => instruction.opcode == OpCodes.Ldloc_0); Plugin.mls.LogInfo((object)$"Index: {num} Code: {list[num]} found."); num++; Plugin.mls.LogInfo((object)$"Got next IL Code: {list[num]}."); list[num + 1].opcode = OpCodes.Nop; num++; list.InsertRange(num, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.PropertyGetter(typeof(Plugin), "CanLivingPlayerReceiveMessage")), new CodeInstruction(OpCodes.Brtrue_S, (object)label), new CodeInstruction(OpCodes.Ret, (object)null), CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Nop, (object)null), new Label[1] { label }) }); } catch (Exception ex3) { Plugin.mls.LogError((object)(ex3.Message + ex3.StackTrace)); throw; } finally { Plugin.mls.LogInfo((object)"Patch success. No any fatal error were raised."); } foreach (CodeInstruction item in list) { yield return item; } } } [HarmonyPatch(typeof(HUDManager), "EnableChat_performed")] internal static class EnableChatPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { HarmonyAPI.LogCallingMethod("EnableChat_performed"); List<CodeInstruction> list = new List<CodeInstruction>(instructions); FieldInfo targetField = typeof(PlayerControllerB).GetField("isPlayerDead"); Plugin.mls.LogInfo((object)"Processing EnableChat_performed method..."); int num; try { num = list.FindLastIndex((CodeInstruction instruction) => instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo fieldInfo && fieldInfo.Equals(targetField)); Plugin.mls.LogInfo((object)$"Index: {num} Code: {list[num]} found."); num -= 2; Plugin.mls.LogInfo((object)$"Got previous IL Code: {list[num]}."); } catch (Exception ex) { Plugin.mls.LogError((object)(ex.Message + ex.StackTrace)); throw; } try { Plugin.mls.LogInfo((object)"Patching following codes..."); for (int i = 0; i <= 4; i++) { Plugin.mls.LogInfo((object)$"Index: {num + i}, Code: {list[num + i]}"); list[num + i].opcode = OpCodes.Nop; } Plugin.mls.LogInfo((object)"Patched codes:"); for (int j = 0; j <= 4; j++) { Plugin.mls.LogInfo((object)$"Index: {num + j}, Code: {list[num + j]}"); } } catch (Exception ex2) { Plugin.mls.LogError((object)(ex2.Message + ex2.StackTrace)); throw; } finally { Plugin.mls.LogInfo((object)"Patch success. No any fatal error were raised."); } foreach (CodeInstruction item in list) { yield return item; } } } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] internal static class SubmitChatPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { HarmonyAPI.LogCallingMethod("SubmitChat_performed"); List<CodeInstruction> list = new List<CodeInstruction>(instructions); FieldInfo targetField = typeof(PlayerControllerB).GetField("isPlayerDead"); Plugin.mls.LogInfo((object)"Processing SubmitChat_performed method..."); int num; try { num = list.FindLastIndex((CodeInstruction instruction) => instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo fieldInfo && fieldInfo.Equals(targetField)); Plugin.mls.LogInfo((object)$"Index: {num} Code: {list[num]} found."); num -= 2; Plugin.mls.LogInfo((object)$"Got previous IL Code: {list[num]}."); } catch (Exception ex) { Plugin.mls.LogError((object)(ex.Message + ex.StackTrace)); throw; } try { Plugin.mls.LogInfo((object)"Patching following codes..."); for (int i = 0; i <= 4; i++) { Plugin.mls.LogInfo((object)$"Index: {num + i}, Code: {list[num + i]}"); list[num + i].opcode = OpCodes.Nop; } Plugin.mls.LogInfo((object)"Patched codes:"); for (int j = 0; j <= 4; j++) { Plugin.mls.LogInfo((object)$"Index: {num + j}, Code: {list[num + j]}"); } } catch (Exception ex2) { Plugin.mls.LogError((object)(ex2.Message + ex2.StackTrace)); throw; } finally { Plugin.mls.LogInfo((object)"Patch success. No any fatal error were raised."); } foreach (CodeInstruction item in list) { yield return item; } } } } namespace SpectatorChat.Other { public static class DebugTestClass { public static void PrintAllVariables() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Global Variables State:"); stringBuilder.AppendLine($"Init: {GlobalVariables.Init}"); stringBuilder.AppendLine($"InitReservedItem: {GlobalVariables.InitReservedItem}"); stringBuilder.AppendLine("HUDElements: " + ((GlobalVariables.HUDElements != null) ? "Initialized" : "Null")); stringBuilder.AppendLine("HUDManagerInstance: " + (((Object)(object)GlobalVariables.HUDManagerInstance != (Object)null) ? "Initialized" : "Null")); stringBuilder.AppendLine("ReservedItemSlot: " + ((GlobalVariables.ReservedItemSlots != null) ? "Initialized" : "Null")); stringBuilder.AppendLine("PlayerControllerInstance: " + (((Object)(object)GlobalVariables.PlayerControllerInstance != (Object)null) ? "Initialized" : "Null")); stringBuilder.AppendLine("CoroutineCancellationTokenSource: " + ((GlobalVariables.CoroutineCancellationTokenSource != null) ? "Initialized" : "Null")); Plugin.mls.LogInfo((object)stringBuilder.ToString()); } } public class GlobalVariables { public static CancellationTokenSource? CoroutineCancellationTokenSource; public static bool Init { get; set; } public static bool InitReservedItem { get; set; } public static List<Image>? ReservedItemSlots { get; set; } public static HUDElement[]? HUDElements { get; set; } public static HUDManager? HUDManagerInstance { get; set; } public static PlayerControllerB? PlayerControllerInstance { get; set; } } public class ReservedItemUI { public static void InitReservedItemUI() { if (Generic.IsModLoaded("FlipMods.ReservedItemSlotCore")) { GlobalVariables.ReservedItemSlots = HUDPatcher.reservedItemSlots; } else { GlobalVariables.ReservedItemSlots = null; } } public static void SwitchReservedItemUI(bool hide) { if (GlobalVariables.ReservedItemSlots == null) { return; } if (hide) { foreach (Image reservedItemSlot in GlobalVariables.ReservedItemSlots) { ((Behaviour)reservedItemSlot).enabled = false; } } foreach (Image reservedItemSlot2 in GlobalVariables.ReservedItemSlots) { ((Behaviour)reservedItemSlot2).enabled = true; } } } } namespace SpectatorChat.API { public class Generic : MonoBehaviour { private static Generic? instance; private Coroutine? _permanentTransparentCoroutine; public static Generic Instance { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null) { instance = new GameObject("SpectatorChatGeneric").AddComponent<Generic>(); } return instance; } } private void Awake() { if ((Object)(object)instance == (Object)null) { instance = this; } else { instance = null; } } public static bool IsInstanceOwner(string userId) { try { return ulong.Parse(userId) == GlobalVariables.PlayerControllerInstance.playerClientId; } catch (Exception ex) { Plugin.mls.LogError((object)(ex.Message + ex.StackTrace)); return false; } } public bool IsCoroutineNull() { if (_permanentTransparentCoroutine == null) { return true; } return false; } public bool StartPermanentTransparent() { Plugin.mls.LogInfo((object)"StartPermanentTransparent() has been called."); if (_permanentTransparentCoroutine == null) { Plugin.mls.LogInfo((object)"Trying to start the coroutine."); GlobalVariables.CoroutineCancellationTokenSource = new CancellationTokenSource(); _permanentTransparentCoroutine = ((MonoBehaviour)this).StartCoroutine(PermanentTransparentCoroutine(GlobalVariables.HUDElements, GlobalVariables.CoroutineCancellationTokenSource)); return true; } return false; } public bool StopPermanentTransparent() { Plugin.mls.LogInfo((object)"StopPermanentTransparent() has been called."); DebugTestClass.PrintAllVariables(); if (_permanentTransparentCoroutine != null && GlobalVariables.CoroutineCancellationTokenSource != null) { Plugin.mls.LogInfo((object)"Trying to stop the coroutine."); GlobalVariables.CoroutineCancellationTokenSource.Cancel(); GlobalVariables.CoroutineCancellationTokenSource = null; _permanentTransparentCoroutine = null; return true; } return false; } public static bool IsModLoaded(string guid) { return Chainloader.PluginInfos.ContainsKey(guid); } private IEnumerator PermanentTransparentCoroutine(HUDElement[] elements, CancellationTokenSource coroutineCancellationTokenSource) { while (!coroutineCancellationTokenSource.IsCancellationRequested) { try { foreach (HUDElement val in elements) { if (val.canvasGroup.alpha != 0f) { val.canvasGroup.alpha = 0f; } } if (IsModLoaded("FlipMods.ReservedItemSlotCore")) { ReservedItemUI.SwitchReservedItemUI(hide: true); } } catch (Exception ex) { Plugin.mls.LogError((object)(ex.Message + ex.StackTrace)); } yield return Plugin.CoroutineDelay.Value; } if (IsModLoaded("FlipMods.ReservedItemSlotCore")) { ReservedItemUI.SwitchReservedItemUI(hide: false); } _permanentTransparentCoroutine = null; } public static void ToggleSpectatorBoxUI(HUDManager instance, bool isVisable) { try { if (isVisable) { for (int i = 0; i < instance.spectatingPlayerBoxes.Count; i++) { ((Component)instance.spectatingPlayerBoxes.ElementAt(i).Key).gameObject.SetActive(true); } } else { for (int j = 0; j < instance.spectatingPlayerBoxes.Count; j++) { ((Component)instance.spectatingPlayerBoxes.ElementAt(j).Key).gameObject.SetActive(false); } } } catch (Exception ex) { Plugin.mls.LogError((object)(ex.Message + ex.StackTrace)); throw; } } public static void ClearSpectatorUI(HUDManager instance) { Plugin.mls.LogInfo((object)"Method ClearSpectatorUI called."); for (int i = 0; i < instance.spectatingPlayerBoxes.Count; i++) { ((Component)instance.spectatingPlayerBoxes.ElementAt(i).Key).gameObject.SetActive(false); instance.boxesAdded--; } instance.yOffsetAmount = 0f; instance.hasGottenPlayerSteamProfilePictures = false; instance.hasLoadedSpectateUI = false; instance.spectatingPlayerBoxes.Clear(); if (instance.spectatingPlayerBoxes.Count != 0) { Plugin.mls.LogInfo((object)"Error. spectatingPlayerBoxes not empty."); } } } public static class HarmonyAPI { public static string GetPatchInfoAsString(Harmony harmony, MethodInfo methodInfo) { MethodInfo methodInfo2 = methodInfo; StringBuilder stringBuilder = new StringBuilder(); foreach (MethodBase item in from method in harmony.GetPatchedMethods() where method == methodInfo2 select method) { stringBuilder.AppendLine("Method " + item.DeclaringType.FullName + "." + item.Name + " is patched by:"); Patches patchInfo = Harmony.GetPatchInfo(item); foreach (Patch prefix in patchInfo.Prefixes) { stringBuilder.AppendLine("- Prefix: " + prefix.owner); } foreach (Patch postfix in patchInfo.Postfixes) { stringBuilder.AppendLine("- Postfix: " + postfix.owner); } foreach (Patch transpiler in patchInfo.Transpilers) { stringBuilder.AppendLine("- Transpiler: " + transpiler.owner); } } return stringBuilder.ToString(); } public static void LogCallingMethod(string patchName) { try { StackFrame[] frames = new StackTrace().GetFrames(); if (frames != null && frames.Length > 1) { MethodBase method = frames[1].GetMethod(); Type? declaringType = method.DeclaringType; string text = declaringType?.Namespace; string text2 = declaringType?.Name; Plugin.mls.LogInfo((object)("Patch " + patchName + " called by: " + text + "." + text2 + "." + method.Name)); } else { Plugin.mls.LogWarning((object)("Unable to determine calling method for patch: " + patchName)); } } catch (Exception ex) { Plugin.mls.LogError((object)("An error occurred while logging calling method for patch " + patchName + ": " + ex.Message)); } } } }