Decompiled source of ShowSpeakerName v1.0.1

plugins/ShowSpeakerName/SBG_ShowSpeakerName.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SBG_ShowSpeakerName.Patches;
using SBG_ShowSpeakerName.SBG_ShowSpeakerName;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
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(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SBG_ShowSpeakerName")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SBG_ShowSpeakerName")]
[assembly: AssemblyTitle("SBG_ShowSpeakerName")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 SBG_ShowSpeakerName
{
	[BepInPlugin("com.themightyryan.showspeakernames", "ShowSpeakerName", "1.0.0")]
	public class ShowSpeakerNamePlugin : BaseUnityPlugin
	{
		public static ManualLogSource Log;

		private static Harmony harmonyInstance;

		private static bool patchesAttempted;

		private void Awake()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[ShowSpeakerName] Plugin loaded and initialised.");
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"[ShowSpeakerName] Static Log initialized.");
			try
			{
				harmonyInstance = new Harmony("com.themightyryan.showspeakernames");
				VoiceChatPatches.ApplyPatches(harmonyInstance);
				patchesAttempted = true;
				harmonyInstance.PatchAll();
				Log.LogInfo((object)"[ShowSpeakerName] Harmony patches applied successfully.");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ShowSpeakerName] Error applying Harmony patches: " + ex.ToString()));
				Log.LogError((object)("[ShowSpeakerName] Stack trace: " + ex.StackTrace));
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private unsafe void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			Log.LogInfo((object)("[ShowSpeakerName] Scene '" + ((Scene)(ref scene)).name + "' loaded (mode: " + ((object)(*(LoadSceneMode*)(&mode))/*cast due to .constrained prefix*/).ToString() + ")."));
			try
			{
				if (!patchesAttempted && harmonyInstance != null)
				{
					Log.LogInfo((object)"[ShowSpeakerName] Retrying VoiceChatPatches on scene load...");
					VoiceChatPatches.ApplyPatches(harmonyInstance);
					patchesAttempted = true;
				}
				if ((Object)(object)GameObject.Find("ShowsSpeakerNameHandler") == (Object)null)
				{
					Log.LogInfo((object)"[ShowSpeakerName] Creating ShowsSpeakerNameHandler GameObject.");
					GameObject val = new GameObject("ShowsSpeakerNameHandler");
					val.AddComponent<ShowSpeakerNameHandler>();
					Object.DontDestroyOnLoad((Object)(object)val);
					Log.LogInfo((object)"[ShowSpeakerName] ShowsSpeakerNameHandler created and marked DontDestroyOnLoad.");
				}
				else
				{
					Log.LogInfo((object)"[ShowSpeakerName] ShowsSpeakerNameHandler already exists.");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ShowSpeakerName] Error in OnSceneLoaded: " + ex.ToString()));
			}
		}
	}
	public class ShowSpeakerNameHandler : MonoBehaviour
	{
		private readonly List<GameObject> processedAvatars = new List<GameObject>();

		private float scanInterval = 0.5f;

		private float timeSinceLastScan = 0f;

		private void Update()
		{
			timeSinceLastScan += Time.deltaTime;
			if (timeSinceLastScan >= scanInterval)
			{
				timeSinceLastScan = 0f;
				ScanForAvatars();
			}
		}

		private void ScanForAvatars()
		{
			try
			{
				IEnumerable<GameObject> enumerable = FindAvatarCandidates();
				int num = 0;
				foreach (GameObject item in enumerable)
				{
					if (!((Object)(object)item == (Object)null) && !processedAvatars.Contains(item))
					{
						processedAvatars.Add(item);
						num++;
					}
				}
			}
			catch (Exception ex)
			{
				ShowSpeakerNamePlugin.Log.LogError((object)("[ShowSpeakerName] Exception in ScanForAvatars: " + ex.ToString()));
			}
		}

		private IEnumerable<GameObject> FindAvatarCandidates()
		{
			RawImage[] array = Resources.FindObjectsOfTypeAll<RawImage>();
			foreach (RawImage rawImage in array)
			{
				if (!((Object)(object)rawImage == (Object)null) && !((Object)(object)((Component)rawImage).gameObject == (Object)null))
				{
					string name = ((Object)((Component)rawImage).gameObject).name.ToLowerInvariant();
					if (IsLikelyAvatarElement(name))
					{
						yield return ((Component)rawImage).gameObject;
					}
				}
			}
			Image[] array2 = Resources.FindObjectsOfTypeAll<Image>();
			foreach (Image image in array2)
			{
				if (!((Object)(object)image == (Object)null) && !((Object)(object)((Component)image).gameObject == (Object)null))
				{
					string name2 = ((Object)((Component)image).gameObject).name.ToLowerInvariant();
					if (IsLikelyAvatarElement(name2))
					{
						yield return ((Component)image).gameObject;
					}
				}
			}
		}

		private bool IsLikelyAvatarElement(string elementName)
		{
			return elementName.Contains("avatar") || elementName.Contains("profile") || elementName.Contains("speaker") || elementName.Contains("voice") || elementName.Contains("steam") || elementName.Contains("portrait") || elementName.Contains("player");
		}
	}
}
namespace SBG_ShowSpeakerName.SBG_ShowSpeakerName
{
	public sealed class SpeakerNameBinding : MonoBehaviour
	{
		public ulong SteamId64;

		public TMP_Text NameLabel;
	}
}
namespace SBG_ShowSpeakerName.Patches
{
	public static class VoiceChatPatches
	{
		public static class VoiceChatUpdatePatch
		{
			public static void Postfix(object __instance)
			{
				try
				{
					FieldInfo field = __instance.GetType().GetField("instances", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field == null)
					{
						return;
					}
					IList list = (IList)field.GetValue(__instance);
					if (list == null || list.Count == 0)
					{
						return;
					}
					Type type = FindTypeInLoadedAssemblies("GameManager");
					if (type == null)
					{
						return;
					}
					PropertyInfo property = type.GetProperty("LocalPlayerInfo", BindingFlags.Static | BindingFlags.Public);
					PropertyInfo property2 = type.GetProperty("RemotePlayers", BindingFlags.Static | BindingFlags.Public);
					if (property == null || property2 == null)
					{
						return;
					}
					object value = property.GetValue(null);
					IList list2 = (IList)property2.GetValue(null);
					if (value == null)
					{
						return;
					}
					if (list.Count > 0)
					{
						object indicatorObject = list[0];
						UpdatePlayerNameLabel(indicatorObject, value);
					}
					if (list2 != null)
					{
						for (int i = 0; i < list2.Count && i + 1 < list.Count; i++)
						{
							object playerInfo = list2[i];
							object indicatorObject2 = list[i + 1];
							UpdatePlayerNameLabel(indicatorObject2, playerInfo);
						}
					}
				}
				catch (Exception ex)
				{
					ShowSpeakerNamePlugin.Log.LogError((object)("[ShowSpeakerName] Exception in VoiceChatUpdatePatch.Postfix: " + ex.ToString()));
					ShowSpeakerNamePlugin.Log.LogError((object)("[ShowSpeakerName] Stack trace: " + ex.StackTrace));
				}
			}
		}

		private static bool patched;

		public static void ApplyPatches(Harmony harmony)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			if (patched)
			{
				return;
			}
			try
			{
				Type type = FindTypeInLoadedAssemblies("VoiceChatIndicatorsHud");
				if (!(type == null))
				{
					MethodInfo method = type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method == null))
					{
						HarmonyMethod val = new HarmonyMethod(typeof(VoiceChatUpdatePatch).GetMethod("Postfix"));
						harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						patched = true;
					}
				}
			}
			catch (Exception ex)
			{
				ShowSpeakerNamePlugin.Log.LogError((object)("[ShowSpeakerName] Exception applying patches: " + ex.ToString()));
				ShowSpeakerNamePlugin.Log.LogError((object)("[ShowSpeakerName] Stack trace: " + ex.StackTrace));
			}
		}

		private static void UpdatePlayerNameLabel(object indicatorObject, object playerInfo)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			if (indicatorObject == null || string.IsNullOrWhiteSpace(playerInfo.ToString()))
			{
				return;
			}
			try
			{
				Type type = indicatorObject.GetType();
				PropertyInfo property = type.GetProperty("gameObject", BindingFlags.Instance | BindingFlags.Public);
				if (property == null)
				{
					Type typeFromHandle = typeof(MonoBehaviour);
					property = typeFromHandle.GetProperty("gameObject", BindingFlags.Instance | BindingFlags.Public);
				}
				object? obj = property?.GetValue(indicatorObject);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Transform val2 = val.transform.Find("PlayerNameLabel");
				PlayerInfo val3 = (PlayerInfo)((playerInfo is PlayerInfo) ? playerInfo : null);
				TextMeshProUGUI val6;
				if ((Object)(object)val2 == (Object)null)
				{
					GameObject val4 = new GameObject("PlayerNameLabel");
					val2 = val4.transform;
					val2.SetParent(val.transform, false);
					RectTransform val5 = val4.AddComponent<RectTransform>();
					val5.anchoredPosition = new Vector2(-140f, 0f);
					val5.sizeDelta = new Vector2(225f, 32f);
					val6 = val4.AddComponent<TextMeshProUGUI>();
					((TMP_Text)val6).fontSize = 24f;
					((TMP_Text)val6).overflowMode = (TextOverflowModes)1;
					((TMP_Text)val6).alignment = (TextAlignmentOptions)516;
					((Graphic)val6).color = Color.white;
					SpeakerNameBinding speakerNameBinding = val4.AddComponent<SpeakerNameBinding>();
					speakerNameBinding.NameLabel = (TMP_Text)(object)val6;
					speakerNameBinding.SteamId64 = val3.PlayerId.Guid;
				}
				else
				{
					val6 = ((Component)val2).GetComponent<TextMeshProUGUI>();
					if ((Object)(object)val6 == (Object)null)
					{
						val6 = ((Component)val2).gameObject.AddComponent<TextMeshProUGUI>();
						((TMP_Text)val6).fontSize = 24f;
						((TMP_Text)val6).overflowMode = (TextOverflowModes)1;
						((TMP_Text)val6).alignment = (TextAlignmentOptions)516;
						((Graphic)val6).color = Color.white;
						SpeakerNameBinding speakerNameBinding2 = ((Component)val2).gameObject.AddComponent<SpeakerNameBinding>();
						speakerNameBinding2.NameLabel = (TMP_Text)(object)val6;
						speakerNameBinding2.SteamId64 = val3.PlayerId.Guid;
					}
				}
				((TMP_Text)val6).text = val3.PlayerId.PlayerName;
				((Component)val2).gameObject.SetActive(true);
			}
			catch (Exception ex)
			{
				ShowSpeakerNamePlugin.Log.LogError((object)("[ShowSpeakerName] Exception updating player name label: " + ex.ToString()));
			}
		}

		private static Type FindTypeInLoadedAssemblies(string typeName)
		{
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					Type type = assembly.GetType(typeName, throwOnError: false);
					if (type != null)
					{
						return type;
					}
				}
			}
			catch (Exception ex)
			{
				ShowSpeakerNamePlugin.Log.LogError((object)("[ShowSpeakerName] Error searching for type " + typeName + ": " + ex.ToString()));
			}
			return null;
		}
	}
}