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;
}
}
}