Decompiled source of AlwaysVisibleNametags v1.1.0

AlwaysVisibleNametags.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
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 TMPro;
using UnityEngine;
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("AlwaysVisibleNametags")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AlwaysVisibleNametags")]
[assembly: AssemblyTitle("AlwaysVisibleNametags")]
[assembly: AssemblyVersion("1.0.0.0")]
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;
		}
	}
}
namespace AlwaysVisibleNametags
{
	internal static class ConfigManager
	{
		public static ConfigEntry<bool>? EnableLivingPlayerModifications { get; private set; }

		public static ConfigEntry<bool>? HideOriginalLivingNameplates { get; private set; }

		public static ConfigEntry<bool>? EnableDeathHeadNameplates { get; private set; }

		public static ConfigEntry<bool>? ShowOwnDeathHeadName { get; private set; }

		public static ConfigEntry<bool>? Living_ReverseNameScale { get; private set; }

		public static ConfigEntry<float>? Living_DefaultScaleMinSize { get; private set; }

		public static ConfigEntry<float>? Living_DefaultScaleMaxSize { get; private set; }

		public static ConfigEntry<float>? Living_DefaultScaleFactor { get; private set; }

		public static ConfigEntry<float>? Living_ReverseScaleMinSize { get; private set; }

		public static ConfigEntry<float>? Living_ReverseScaleMaxSize { get; private set; }

		public static ConfigEntry<float>? Living_ReverseScaleFactor { get; private set; }

		public static ConfigEntry<float>? DeathHead_YOffset { get; private set; }

		public static ConfigEntry<bool>? DeathHead_ReverseNameScale { get; private set; }

		public static ConfigEntry<float>? DeathHead_DefaultScaleMinSize { get; private set; }

		public static ConfigEntry<float>? DeathHead_DefaultScaleMaxSize { get; private set; }

		public static ConfigEntry<float>? DeathHead_DefaultScaleFactor { get; private set; }

		public static ConfigEntry<float>? DeathHead_ReverseScaleMinSize { get; private set; }

		public static ConfigEntry<float>? DeathHead_ReverseScaleMaxSize { get; private set; }

		public static ConfigEntry<float>? DeathHead_ReverseScaleFactor { get; private set; }

		public static void Initialize(ConfigFile config)
		{
			EnableLivingPlayerModifications = config.Bind<bool>("1. General", "EnableLivingPlayerModifications", true, "Master switch for ALL modifications to living player nameplates (always visible, custom scaling, etc.).\nIf false, living player nameplates behave exactly like the vanilla game (except maybe hidden if HideOriginalLivingNameplates is true).");
			HideOriginalLivingNameplates = config.Bind<bool>("1. General", "HideOriginalLivingNameplates", false, "If true, completely hides the default nameplates above living players.\nThis takes precedence over EnableLivingPlayerModifications for visibility.");
			EnableDeathHeadNameplates = config.Bind<bool>("1. General", "EnableDeathHeadNameplates", true, "Master switch for adding nameplates to player death heads.");
			ShowOwnDeathHeadName = config.Bind<bool>("1. General", "ShowOwnDeathHeadName", true, "If true (and EnableDeathHeadNameplates is true), you will see the nameplate above your own PlayerDeathHead when you die.");
			Living_ReverseNameScale = config.Bind<bool>("2. Living Player Nameplate Scaling", "Living_ReverseNameScale", false, "If true, nameplates get LARGER as they get farther away. If false, they get smaller (Default Scaling).");
			Living_DefaultScaleMaxSize = config.Bind<float>("2. Living Player Nameplate Scaling", "Living_DefaultScaleMaxSize", 20f, "[Default Scaling] The maximum font size (when close). Affects living player nameplates.");
			Living_DefaultScaleMinSize = config.Bind<float>("2. Living Player Nameplate Scaling", "Living_DefaultScaleMinSize", 0f, "[Default Scaling] The minimum font size nameplates will shrink to (e.g., 0 to disappear completely). Affects living player nameplates.");
			Living_DefaultScaleFactor = config.Bind<float>("2. Living Player Nameplate Scaling", "Living_DefaultScaleFactor", 0.8f, "[Default Scaling] How quickly font size decreases with distance. Higher = faster shrinking. Affects living player nameplates.");
			Living_ReverseScaleMinSize = config.Bind<float>("2. Living Player Nameplate Scaling", "Living_ReverseScaleMinSize", 4f, "[Reverse Scaling] The font size when close. Affects living player nameplates.");
			Living_ReverseScaleMaxSize = config.Bind<float>("2. Living Player Nameplate Scaling", "Living_ReverseScaleMaxSize", 22f, "[Reverse Scaling] The maximum font size limit when far. Affects living player nameplates.");
			Living_ReverseScaleFactor = config.Bind<float>("2. Living Player Nameplate Scaling", "Living_ReverseScaleFactor", 0.7f, "[Reverse Scaling] How quickly font size increases with distance. Higher = faster growing. Affects living player nameplates.");
			DeathHead_YOffset = config.Bind<float>("3. Death Head Nameplate", "DeathHead_YOffset", 0.3f, "The vertical distance (Y-offset) the nameplate appears above a PlayerDeathHead.");
			DeathHead_ReverseNameScale = config.Bind<bool>("3. Death Head Nameplate", "DeathHead_ReverseNameScale", false, "If true, nameplates get LARGER as they get farther away. If false, they get smaller (Default Scaling).");
			DeathHead_DefaultScaleMaxSize = config.Bind<float>("3. Death Head Nameplate", "DeathHead_DefaultScaleMaxSize", 20f, "[Default Scaling] The maximum font size (when close). Affects death head nameplates.");
			DeathHead_DefaultScaleMinSize = config.Bind<float>("3. Death Head Nameplate", "DeathHead_DefaultScaleMinSize", 0f, "[Default Scaling] The minimum font size nameplates will shrink to. Affects death head nameplates.");
			DeathHead_DefaultScaleFactor = config.Bind<float>("3. Death Head Nameplate", "DeathHead_DefaultScaleFactor", 0.8f, "[Default Scaling] How quickly font size decreases with distance. Higher = faster shrinking. Affects death head nameplates.");
			DeathHead_ReverseScaleMinSize = config.Bind<float>("3. Death Head Nameplate", "DeathHead_ReverseScaleMinSize", 4f, "[Reverse Scaling] The font size when close. Affects death head nameplates.");
			DeathHead_ReverseScaleMaxSize = config.Bind<float>("3. Death Head Nameplate", "DeathHead_ReverseScaleMaxSize", 22f, "[Reverse Scaling] The maximum font size limit when far. Affects death head nameplates.");
			DeathHead_ReverseScaleFactor = config.Bind<float>("3. Death Head Nameplate", "DeathHead_ReverseScaleFactor", 0.7f, "[Reverse Scaling] How quickly font size increases with distance. Higher = faster growing. Affects death head nameplates.");
			AlwaysVisibleNametagsMod.LogInstance.LogInfo((object)"Configuration loaded.");
		}
	}
	public static class NameplateManager
	{
		public static readonly Dictionary<PlayerDeathHead, WorldSpaceUIDeathHeadName> deathHeadNameplates = new Dictionary<PlayerDeathHead, WorldSpaceUIDeathHeadName>();

		public static void CreateDeathHeadNameplate(PlayerDeathHead head)
		{
			if ((Object)(object)head == (Object)null || (Object)(object)head.playerAvatar == (Object)null)
			{
				AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)"Attempted to create death head nameplate for null head or avatar.");
				return;
			}
			string text = ReflectionUtils.GetPlayerAvatarPlayerName(head.playerAvatar);
			if (string.IsNullOrEmpty(text) || text == "Unknown")
			{
				text = $"Player_{((Object)head.playerAvatar).GetInstanceID()}";
				AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)$"Could not get valid player name for head {((Object)head).GetInstanceID()}. Using fallback: {text}");
			}
			if (deathHeadNameplates.TryGetValue(head, out WorldSpaceUIDeathHeadName value))
			{
				if (!((Object)(object)value == (Object)null))
				{
					return;
				}
				AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)("Found null nameplate reference for " + text + " in dictionary. Removing entry."));
				deathHeadNameplates.Remove(head);
			}
			bool playerAvatarIsLocal = ReflectionUtils.GetPlayerAvatarIsLocal(head.playerAvatar);
			if (playerAvatarIsLocal)
			{
				ConfigEntry<bool>? showOwnDeathHeadName = ConfigManager.ShowOwnDeathHeadName;
				if (showOwnDeathHeadName != null && !showOwnDeathHeadName.Value)
				{
					return;
				}
			}
			WorldSpaceUIParent instance = WorldSpaceUIParent.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerNamePrefab == (Object)null)
			{
				AlwaysVisibleNametagsMod.LogInstance.LogError((object)"WorldSpaceUIParent instance or playerNamePrefab is null. Cannot create death head nameplate.");
				return;
			}
			AlwaysVisibleNametagsMod.LogInstance.LogInfo((object)$"Creating death head nameplate for {text} (IsLocal={playerAvatarIsLocal})...");
			GameObject val = null;
			try
			{
				val = Object.Instantiate<GameObject>(instance.playerNamePrefab, ((Component)instance).transform);
				((Object)val).name = "DeathHeadName_" + text;
				WorldSpaceUIPlayerName val2 = default(WorldSpaceUIPlayerName);
				if (val.TryGetComponent<WorldSpaceUIPlayerName>(ref val2))
				{
					Object.Destroy((Object)(object)val2);
				}
				WorldSpaceUIDeathHeadName worldSpaceUIDeathHeadName = val.AddComponent<WorldSpaceUIDeathHeadName>();
				worldSpaceUIDeathHeadName.Initialize(head);
				if ((Object)(object)worldSpaceUIDeathHeadName != (Object)null && (Object)(object)worldSpaceUIDeathHeadName.text != (Object)null)
				{
					if (!string.IsNullOrEmpty(((TMP_Text)worldSpaceUIDeathHeadName.text).text) && ((TMP_Text)worldSpaceUIDeathHeadName.text).text != "Default")
					{
						deathHeadNameplates[head] = worldSpaceUIDeathHeadName;
						return;
					}
					AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)("Initialization seems to have failed for " + text + "'s nameplate (text empty/default after init). It should have self-destructed."));
					if ((Object)(object)val != (Object)null && !((object)val).Equals((object?)null))
					{
						Object.Destroy((Object)(object)val);
					}
				}
				else
				{
					AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)("Initialization seems to have failed for " + text + "'s nameplate (component or text is null after init). It should have self-destructed."));
					if ((Object)(object)val != (Object)null && !((object)val).Equals((object?)null))
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
			catch (Exception arg)
			{
				AlwaysVisibleNametagsMod.LogInstance.LogError((object)$"Exception during death head nameplate creation for {text}: {arg}");
				if ((Object)(object)val != (Object)null && !((object)val).Equals((object?)null))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		public static void DestroyDeathHeadNameplate(PlayerDeathHead head)
		{
			if ((Object)(object)head != (Object)null && deathHeadNameplates.TryGetValue(head, out WorldSpaceUIDeathHeadName value))
			{
				deathHeadNameplates.Remove(head);
				if ((Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null)
				{
					TextMeshProUGUI text = value.text;
					string text2 = ((text != null) ? ((TMP_Text)text).text : null) ?? (((Object)(object)head.playerAvatar != (Object)null) ? ReflectionUtils.GetPlayerAvatarPlayerName(head.playerAvatar) : "Unknown");
					AlwaysVisibleNametagsMod.LogInstance.LogInfo((object)("Destroying death head nameplate object for " + text2 + "."));
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
				else
				{
					AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)$"Attempted to destroy nameplate for head {((Object)head).GetInstanceID()}, but nameplate reference or GameObject was null.");
				}
			}
		}

		public static void ClearAllDeathHeadNameplates()
		{
			AlwaysVisibleNametagsMod.LogInstance.LogInfo((object)$"Clearing {deathHeadNameplates.Count} tracked death head nameplates.");
			List<WorldSpaceUIDeathHeadName> list = new List<WorldSpaceUIDeathHeadName>(deathHeadNameplates.Values);
			deathHeadNameplates.Clear();
			foreach (WorldSpaceUIDeathHeadName item in list)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)((Component)item).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
				}
			}
		}
	}
	[BepInPlugin("nilaier.alwaysvisiblenametags", "Always Visible Nametags", "1.1.0")]
	public class AlwaysVisibleNametagsMod : BaseUnityPlugin
	{
		internal static ManualLogSource LogInstance;

		private Harmony harmony;

		internal const string MOD_GUID = "nilaier.alwaysvisiblenametags";

		internal const string MOD_NAME = "Always Visible Nametags";

		internal const string MOD_VERSION = "1.1.0";

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			LogInstance = ((BaseUnityPlugin)this).Logger;
			LogInstance.LogInfo((object)"Always Visible Nametags v1.1.0 is loading...");
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			harmony = new Harmony("nilaier.alwaysvisiblenametags");
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			LogInstance.LogInfo((object)"Harmony patches applied.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			LogInstance.LogInfo((object)"Always Visible Nametags unloaded and patches removed.");
			NameplateManager.ClearAllDeathHeadNameplates();
		}
	}
	[HarmonyPatch(typeof(WorldSpaceUIPlayerName), "Update")]
	public static class WorldSpaceUIPlayerName_Update_Patch
	{
		private static readonly FieldInfo playerAvatarField = AccessTools.Field(typeof(WorldSpaceUIPlayerName), "playerAvatar");

		private static Camera? _mainCameraCache;

		public static void Postfix(WorldSpaceUIPlayerName __instance)
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			ConfigEntry<bool>? hideOriginalLivingNameplates = ConfigManager.HideOriginalLivingNameplates;
			if (hideOriginalLivingNameplates != null && hideOriginalLivingNameplates.Value)
			{
				if (((Component)__instance).gameObject.activeSelf)
				{
					((Component)__instance).gameObject.SetActive(false);
				}
			}
			else
			{
				if (!((Component)__instance).gameObject.activeSelf || (Object)(object)__instance.text == (Object)null)
				{
					return;
				}
				ConfigEntry<bool>? enableLivingPlayerModifications = ConfigManager.EnableLivingPlayerModifications;
				if (enableLivingPlayerModifications != null && !enableLivingPlayerModifications.Value)
				{
					return;
				}
				if ((Object)(object)_mainCameraCache == (Object)null)
				{
					_mainCameraCache = Camera.main;
				}
				if ((Object)(object)_mainCameraCache == (Object)null)
				{
					return;
				}
				object? value = playerAvatarField.GetValue(__instance);
				PlayerAvatar val = (PlayerAvatar)((value is PlayerAvatar) ? value : null);
				if (val == null)
				{
					return;
				}
				float num = Vector3.Distance(ReflectionUtils.GetWorldSpaceUIChildWorldPosition((WorldSpaceUIChild)(object)__instance), ((Component)_mainCameraCache).transform.position);
				bool num2 = ConfigManager.Living_ReverseNameScale?.Value ?? false;
				float num3 = ConfigManager.Living_ReverseScaleMinSize?.Value ?? 4f;
				float num4 = ConfigManager.Living_ReverseScaleMaxSize?.Value ?? 22f;
				float num5 = ConfigManager.Living_ReverseScaleFactor?.Value ?? 0.7f;
				float num6 = ConfigManager.Living_DefaultScaleMinSize?.Value ?? 0f;
				float num7 = ConfigManager.Living_DefaultScaleMaxSize?.Value ?? 20f;
				float num8 = ConfigManager.Living_DefaultScaleFactor?.Value ?? 0.8f;
				float num9;
				if (num2)
				{
					num9 = num3 + num * num5;
					num9 = Mathf.Clamp(num9, num3, num4);
				}
				else
				{
					num9 = num7 - num * num8;
					num9 = Mathf.Clamp(num9, num6, num7);
				}
				if (!Mathf.Approximately(((TMP_Text)__instance.text).fontSize, num9))
				{
					((TMP_Text)__instance.text).fontSize = num9;
				}
				if (!ReflectionUtils.GetPlayerAvatarIsDisabled(val))
				{
					Graphic text = (Graphic)(object)__instance.text;
					if (text != null && text.color.a < 1f)
					{
						Color color = text.color;
						text.color = new Color(color.r, color.g, color.b, 1f);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerDeathHead), "Trigger")]
	public static class PlayerDeathHead_Trigger_Patch
	{
		public static void Postfix(PlayerDeathHead __instance)
		{
			ConfigEntry<bool>? enableDeathHeadNameplates = ConfigManager.EnableDeathHeadNameplates;
			if (enableDeathHeadNameplates == null || enableDeathHeadNameplates.Value)
			{
				if ((Object)(object)__instance != (Object)null)
				{
					NameplateManager.CreateDeathHeadNameplate(__instance);
				}
				else
				{
					AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)"PlayerDeathHead.Trigger Postfix called with null instance.");
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerDeathHead), "Reset")]
	public static class PlayerDeathHead_Reset_Patch
	{
		public static void Postfix(PlayerDeathHead __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				NameplateManager.DestroyDeathHeadNameplate(__instance);
			}
			else
			{
				AlwaysVisibleNametagsMod.LogInstance.LogWarning((object)"PlayerDeathHead.Reset Postfix called with null instance.");
			}
		}
	}
	internal static class ReflectionUtils
	{
		private static readonly FieldInfo? _playerAvatar_isDisabled;

		private static readonly FieldInfo? _playerAvatar_playerName;

		private static readonly FieldInfo? _playerDeathHead_triggered;

		private static readonly FieldInfo? _worldSpaceUIChild_worldPosition;

		private static readonly FieldInfo? _playerAvatar_isLocal;

		static ReflectionUtils()
		{
			_playerAvatar_isDisabled = AccessTools.Field(typeof(PlayerAvatar), "isDisabled");
			_playerAvatar_playerName = AccessTools.Field(typeof(PlayerAvatar), "playerName");
			_playerDeathHead_triggered = AccessTools.Field(typeof(PlayerDeathHead), "triggered");
			_worldSpaceUIChild_worldPosition = AccessTools.Field(typeof(WorldSpaceUIChild), "worldPosition");
			_playerAvatar_isLocal = AccessTools.Field(typeof(PlayerAvatar), "isLocal");
			EnsureField(_playerAvatar_isDisabled, "PlayerAvatar", "isDisabled");
			EnsureField(_playerAvatar_playerName, "PlayerAvatar", "playerName");
			EnsureField(_playerDeathHead_triggered, "PlayerDeathHead", "triggered");
			EnsureField(_worldSpaceUIChild_worldPosition, "WorldSpaceUIChild", "worldPosition");
			EnsureField(_playerAvatar_isLocal, "PlayerAvatar", "isLocal");
		}

		private static void EnsureField(FieldInfo? field, string typeName, string fieldName)
		{
			if (field == null)
			{
				ManualLogSource logInstance = AlwaysVisibleNametagsMod.LogInstance;
				if (logInstance != null)
				{
					logInstance.LogError((object)("Reflection failed: Could not find field '" + fieldName + "' on type '" + typeName + "'. Mod functionality may be broken."));
				}
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool GetPlayerAvatarIsDisabled(PlayerAvatar instance)
		{
			try
			{
				if ((Object)(object)instance != (Object)null && _playerAvatar_isDisabled != null)
				{
					return (bool)_playerAvatar_isDisabled.GetValue(instance);
				}
			}
			catch (Exception ex)
			{
				LogReflectionError("GetPlayerAvatarIsDisabled", ex);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static string GetPlayerAvatarPlayerName(PlayerAvatar instance)
		{
			try
			{
				if ((Object)(object)instance != (Object)null && _playerAvatar_playerName != null)
				{
					return ((string)_playerAvatar_playerName.GetValue(instance)) ?? "Unknown";
				}
			}
			catch (Exception ex)
			{
				LogReflectionError("GetPlayerAvatarPlayerName", ex);
			}
			return "Unknown";
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool GetPlayerAvatarIsLocal(PlayerAvatar instance)
		{
			try
			{
				if ((Object)(object)instance != (Object)null && _playerAvatar_isLocal != null)
				{
					return (bool)_playerAvatar_isLocal.GetValue(instance);
				}
			}
			catch (Exception ex)
			{
				LogReflectionError("GetPlayerAvatarIsLocal", ex);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool GetPlayerDeathHeadTriggered(PlayerDeathHead instance)
		{
			try
			{
				if ((Object)(object)instance != (Object)null && _playerDeathHead_triggered != null)
				{
					return (bool)_playerDeathHead_triggered.GetValue(instance);
				}
			}
			catch (Exception ex)
			{
				LogReflectionError("GetPlayerDeathHeadTriggered", ex);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Vector3 GetWorldSpaceUIChildWorldPosition(WorldSpaceUIChild instance)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)instance != (Object)null && _worldSpaceUIChild_worldPosition != null)
				{
					return (Vector3)_worldSpaceUIChild_worldPosition.GetValue(instance);
				}
			}
			catch (Exception ex)
			{
				LogReflectionError("GetWorldSpaceUIChildWorldPosition", ex);
			}
			return Vector3.zero;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void SetWorldSpaceUIChildWorldPosition(WorldSpaceUIChild instance, Vector3 value)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)instance != (Object)null && _worldSpaceUIChild_worldPosition != null)
				{
					_worldSpaceUIChild_worldPosition.SetValue(instance, value);
				}
			}
			catch (Exception ex)
			{
				LogReflectionError("SetWorldSpaceUIChildWorldPosition", ex);
			}
		}

		private static void LogReflectionError(string methodName, Exception ex)
		{
			ManualLogSource logInstance = AlwaysVisibleNametagsMod.LogInstance;
			if (logInstance != null)
			{
				logInstance.LogError((object)("Reflection error in " + methodName + ": " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}
	public class WorldSpaceUIDeathHeadName : WorldSpaceUIChild
	{
		public TextMeshProUGUI text;

		internal PlayerDeathHead targetHead;

		private Camera? _mainCameraCache;

		protected override void Update()
		{
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)targetHead == (Object)null || !((Component)targetHead).gameObject.activeSelf || (Object)(object)targetHead.playerAvatar == (Object)null)
			{
				if ((Object)(object)((Component)this).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
				return;
			}
			if ((Object)(object)_mainCameraCache == (Object)null)
			{
				_mainCameraCache = Camera.main;
			}
			if ((Object)(object)_mainCameraCache == (Object)null)
			{
				return;
			}
			bool playerDeathHeadTriggered = ReflectionUtils.GetPlayerDeathHeadTriggered(targetHead);
			bool playerAvatarIsLocal = ReflectionUtils.GetPlayerAvatarIsLocal(targetHead.playerAvatar);
			int num;
			if (playerDeathHeadTriggered)
			{
				ConfigEntry<bool>? enableDeathHeadNameplates = ConfigManager.EnableDeathHeadNameplates;
				if (enableDeathHeadNameplates == null || enableDeathHeadNameplates.Value)
				{
					num = ((!playerAvatarIsLocal || (ConfigManager.ShowOwnDeathHeadName?.Value ?? true)) ? 1 : 0);
					goto IL_00c0;
				}
			}
			num = 0;
			goto IL_00c0;
			IL_00c0:
			bool flag = (byte)num != 0;
			if ((Object)(object)text == (Object)null)
			{
				AlwaysVisibleNametagsMod.LogInstance.LogError((object)("Text component is null on DeathHeadNameplate for " + ReflectionUtils.GetPlayerAvatarPlayerName(targetHead.playerAvatar) + ". Destroying self."));
				if ((Object)(object)((Component)this).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
				return;
			}
			if (((Behaviour)text).enabled != flag)
			{
				((Behaviour)text).enabled = flag;
				AlwaysVisibleNametagsMod.LogInstance.LogDebug((object)$"Set death head text enabled for {ReflectionUtils.GetPlayerAvatarPlayerName(targetHead.playerAvatar)} to {flag}");
			}
			if (flag)
			{
				float num2 = ConfigManager.DeathHead_YOffset?.Value ?? 0.3f;
				Vector3 val = ((Component)targetHead).transform.position + Vector3.up * num2;
				ReflectionUtils.SetWorldSpaceUIChildWorldPosition((WorldSpaceUIChild)(object)this, val);
				((WorldSpaceUIChild)this).Update();
				float num3 = Vector3.Distance(val, ((Component)_mainCameraCache).transform.position);
				bool num4 = ConfigManager.DeathHead_ReverseNameScale?.Value ?? false;
				float num5 = ConfigManager.DeathHead_ReverseScaleMinSize?.Value ?? 4f;
				float num6 = ConfigManager.DeathHead_ReverseScaleMaxSize?.Value ?? 22f;
				float num7 = ConfigManager.DeathHead_ReverseScaleFactor?.Value ?? 0.7f;
				float num8 = ConfigManager.DeathHead_DefaultScaleMinSize?.Value ?? 0f;
				float num9 = ConfigManager.DeathHead_DefaultScaleMaxSize?.Value ?? 20f;
				float num10 = ConfigManager.DeathHead_DefaultScaleFactor?.Value ?? 0.8f;
				float num11;
				if (num4)
				{
					num11 = num5 + num3 * num7;
					num11 = Mathf.Clamp(num11, num5, num6);
				}
				else
				{
					num11 = num9 - num3 * num10;
					num11 = Mathf.Clamp(num11, num8, num9);
				}
				if (!Mathf.Approximately(((TMP_Text)text).fontSize, num11))
				{
					((TMP_Text)text).fontSize = num11;
				}
				Graphic val2 = (Graphic)(object)text;
				if (val2 != null && val2.color.a < 1f)
				{
					Color color = val2.color;
					val2.color = new Color(color.r, color.g, color.b, 1f);
				}
			}
		}

		public void Initialize(PlayerDeathHead head)
		{
			targetHead = head;
			if ((Object)(object)targetHead == (Object)null || (Object)(object)targetHead.playerAvatar == (Object)null)
			{
				AlwaysVisibleNametagsMod.LogInstance.LogError((object)"Failed to initialize death head nameplate: Target head or PlayerAvatar is null. Destroying.");
				if ((Object)(object)((Component)this).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
				return;
			}
			text = ((Component)this).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)text == (Object)null)
			{
				AlwaysVisibleNametagsMod.LogInstance.LogError((object)("Failed to find TextMeshProUGUI component for death head nameplate [" + ReflectionUtils.GetPlayerAvatarPlayerName(targetHead.playerAvatar) + "]. Destroying."));
				if ((Object)(object)((Component)this).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
			}
			else
			{
				string playerAvatarPlayerName = ReflectionUtils.GetPlayerAvatarPlayerName(targetHead.playerAvatar);
				((TMP_Text)text).text = playerAvatarPlayerName;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)targetHead != (Object)null && NameplateManager.deathHeadNameplates.ContainsKey(targetHead))
			{
				NameplateManager.deathHeadNameplates.Remove(targetHead);
			}
		}
	}
}