Decompiled source of WalkieTalkies v1.5.2

EmpressWalkieTalkies.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("EMPRESS")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0+5f1b735e473ca4ccf3b383128fbebd889cb564da")]
[assembly: AssemblyProduct("EMPRESS Walkie Talkies")]
[assembly: AssemblyTitle("EmpressWalkieTalkies")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.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 Empress.WalkieTalkies
{
	[BepInPlugin("empress.repo.walkietalkies", "EMPRESS Walkie Talkies", "1.3.0")]
	public class EmpressWalkieTalkiesPlugin : BaseUnityPlugin
	{
		[HarmonyPatch]
		internal static class Patch_AttachController
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(PlayerVoiceChat), "Awake", (Type[])null, (Type[])null);
			}

			private static void Postfix(PlayerVoiceChat __instance)
			{
				WalkieController walkieController = default(WalkieController);
				if (!((Component)__instance).gameObject.TryGetComponent<WalkieController>(ref walkieController))
				{
					((Component)__instance).gameObject.AddComponent<WalkieController>();
				}
			}
		}

		[HarmonyPatch]
		internal static class Patch_RightArmPose
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(PlayerAvatarRightArm), "Update", (Type[])null, (Type[])null);
			}

			private static bool Prefix(PlayerAvatarRightArm __instance)
			{
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (WalkieController.PlayersTalking.Contains(__instance.playerAvatar.photonView.ViewID))
					{
						__instance.SetPose(WalkieController.WalkiePose);
						__instance.HeadAnimate(false);
						__instance.AnimatePose();
						return false;
					}
				}
				catch
				{
				}
				return true;
			}
		}

		public class WalkieController : MonoBehaviourPun
		{
			public static readonly HashSet<int> PlayersTalking = new HashSet<int>();

			public static readonly Vector3 WalkiePose = new Vector3(0f, -30f, 0f);

			private const string BundleBase = "walky";

			private const string PrefabName = "Talky";

			private const string SfxOnName = "OnSound";

			private const string SfxOffName = "OffSound";

			private const string SfxIdleName = "IdleOnSound";

			private static readonly Vector3 TalkiePos = new Vector3(-0.1f, -0.05f, 0.3f);

			private static readonly Quaternion TalkieRotation = Quaternion.Euler(350f, 179f, 45f);

			private static readonly Vector3 RemoteTalkiePos = new Vector3(-0.15f, -0.25f, 0.65f);

			private static readonly Quaternion RemoteTalkieRotation = Quaternion.Euler(15f, 215f, 345f);

			private static readonly int ColorProperty = Shader.PropertyToID("_Color");

			private static readonly int BaseColorProperty = Shader.PropertyToID("_BaseColor");

			private static readonly int AlbedoColorProperty = Shader.PropertyToID("_AlbedoColor");

			private static readonly int EmissionColorProperty = Shader.PropertyToID("_EmissionColor");

			private static readonly int FresnelColorProperty = Shader.PropertyToID("_FresnelColor");

			private bool _bootstrapped;

			private PlayerAvatar _localAvatar = null;

			private int _avatarViewId = -1;

			private float _maxBattery;

			private float _battery;

			private bool _recharge;

			private bool _enemiesHear;

			private KeyCode _pushKey = (KeyCode)118;

			private WalkieBatteryUI _batteryUi = null;

			private GameObject _armRoot = null;

			private Transform? _localParent;

			private GameObject _talkieLocal = null;

			private GameObject _talkieRemote = null;

			private AudioSource? _sfxOn;

			private AudioSource? _sfxOff;

			private AudioSource? _sfxIdle;

			private bool _usingRadio;

			private bool _canToggle = true;

			private Color _talkieColor = new Color(0.87f, 0.69f, 1f, 1f);

			private string _talkieColorHex = "#DDB0FF";

			private string _lastWalkieColorConfig = string.Empty;

			private void OnEnable()
			{
				SceneManager.sceneLoaded += OnSceneLoaded;
			}

			private void OnDisable()
			{
				SceneManager.sceneLoaded -= OnSceneLoaded;
			}

			private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
			{
				if (!IsInGame())
				{
					_bootstrapped = false;
					if (IsMasterOrSingle())
					{
						MaxBattery = CFG_MaxBattery.Value;
						Recharge = CFG_Recharge.Value;
						EnemiesHear = CFG_EnemiesHear.Value;
						((MonoBehaviourPun)this).photonView.RPC("RPC_SyncSettings", (RpcTarget)0, new object[3] { MaxBattery, Recharge, EnemiesHear });
					}
				}
			}

			private void Start()
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				TryResolveKey(CFG_TalkKey.Value);
				_lastWalkieColorConfig = CFG_WalkieColor.Value;
				_talkieColor = LocalColor;
				_talkieColorHex = LocalColorHex;
			}

			private void Update()
			{
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_011d: Unknown result type (might be due to invalid IL or missing references)
				if (!((MonoBehaviourPun)this).photonView.IsMine)
				{
					return;
				}
				RefreshLocalColorConfig();
				bool flag = IsInGame();
				if (flag && !_bootstrapped)
				{
					_bootstrapped = true;
					Bootstrap();
				}
				if (!flag || (Object)(object)_localAvatar == (Object)null || _localAvatar.spectating)
				{
					if (_usingRadio)
					{
						ForceStopTalking();
					}
					if ((Object)(object)_batteryUi != (Object)null && ((Component)_batteryUi).gameObject.activeSelf)
					{
						((Component)_batteryUi).gameObject.SetActive(false);
					}
					return;
				}
				if ((Object)(object)_batteryUi != (Object)null && !((Component)_batteryUi).gameObject.activeSelf)
				{
					((Component)_batteryUi).gameObject.SetActive(true);
				}
				if (Input.GetKey(_pushKey))
				{
					BeginTalking();
				}
				else if (Input.GetKeyUp(_pushKey))
				{
					EndTalking();
				}
				TickBattery();
				AnimateLocalArm();
				UpdateSfxVisibility();
			}

			private void Bootstrap()
			{
				//IL_003a: 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)
				_maxBattery = MaxBattery;
				_battery = Mathf.Max(0f, _maxBattery);
				_recharge = Recharge;
				_enemiesHear = EnemiesHear;
				_talkieColor = LocalColor;
				_talkieColorHex = LocalColorHex;
				PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>();
				foreach (PlayerAvatar val in array)
				{
					if (val.photonView.IsMine)
					{
						_localAvatar = val;
						break;
					}
				}
				if ((Object)(object)_localAvatar == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)"[EMPRESS Walkie Talkies] No local PlayerAvatar yet.");
					}
					return;
				}
				_avatarViewId = _localAvatar.photonView.ViewID;
				_localParent = FindGrabberTarget(((Component)_localAvatar).transform);
				if ((Object)(object)_localParent == (Object)null)
				{
					_localParent = (((Object)(object)((Component)_localAvatar).transform.parent != (Object)null) ? ((Component)_localAvatar).transform.parent.Find("Local Camera") : null);
				}
				TryCreateBatteryUi();
				TryCreateLocalTalkie();
				PublishLocalColor();
				((MonoBehaviourPun)this).photonView.RPC("RPC_CreateRemoteTalkieOnRightArm", (RpcTarget)4, new object[1] { _avatarViewId });
				((MonoBehaviourPun)this).photonView.RPC("RPC_SetLocalAvatarViewId", (RpcTarget)0, new object[1] { _avatarViewId });
			}

			internal void PublishLocalColor()
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				_talkieColor = LocalColor;
				_talkieColorHex = LocalColorHex;
				ApplyWalkieColor(_talkieLocal, _talkieColor);
				if ((Object)(object)_batteryUi != (Object)null)
				{
					_batteryUi.Tint(_talkieColor);
				}
				if (!((Object)(object)_localAvatar == (Object)null))
				{
					_avatarViewId = _localAvatar.photonView.ViewID;
					if (PhotonNetwork.InRoom)
					{
						PhotonNetwork.RemoveBufferedRPCs(((MonoBehaviourPun)this).photonView.ViewID, "RPC_SetWalkieColor", (int[])null);
						((MonoBehaviourPun)this).photonView.RPC("RPC_SetWalkieColor", (RpcTarget)3, new object[5] { _avatarViewId, _talkieColor.r, _talkieColor.g, _talkieColor.b, _talkieColorHex });
					}
					else
					{
						RPC_SetWalkieColor(_avatarViewId, _talkieColor.r, _talkieColor.g, _talkieColor.b, _talkieColorHex);
					}
				}
			}

			private void RefreshLocalColorConfig()
			{
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				string value = CFG_WalkieColor.Value;
				if (!string.Equals(value, _lastWalkieColorConfig, StringComparison.Ordinal))
				{
					_lastWalkieColorConfig = value;
					RefreshLocalColor();
					if ((Object)(object)_localAvatar != (Object)null)
					{
						PublishLocalColor();
						return;
					}
					_talkieColor = LocalColor;
					_talkieColorHex = LocalColorHex;
				}
			}

			private void BeginTalking()
			{
				if (!_usingRadio && _canToggle && !(_battery <= 1f))
				{
					_usingRadio = true;
					if ((Object)(object)_talkieLocal != (Object)null && !_talkieLocal.activeSelf)
					{
						_talkieLocal.SetActive(true);
					}
					((MonoBehaviourPun)this).photonView.RPC("RPC_SetVoiceRangeAndFilters", (RpcTarget)0, new object[2] { 10000, true });
					((MonoBehaviourPun)this).photonView.RPC("RPC_SetTalkingFlag", (RpcTarget)0, new object[2]
					{
						_localAvatar.photonView.ViewID,
						true
					});
					((MonoBehaviourPun)this).photonView.RPC("RPC_ShowRemoteTalkie", (RpcTarget)1, new object[1] { true });
				}
			}

			private void EndTalking()
			{
				if (_usingRadio)
				{
					_usingRadio = false;
					((MonoBehaviourPun)this).photonView.RPC("RPC_ShowRemoteTalkie", (RpcTarget)1, new object[1] { false });
					((MonoBehaviourPun)this).photonView.RPC("RPC_SetTalkingFlag", (RpcTarget)0, new object[2]
					{
						_localAvatar.photonView.ViewID,
						false
					});
					((MonoBehaviour)this).StartCoroutine(StopTalkingAfter(0.4f));
				}
			}

			private void ForceStopTalking()
			{
				_usingRadio = false;
				((MonoBehaviourPun)this).photonView.RPC("RPC_ShowRemoteTalkie", (RpcTarget)1, new object[1] { false });
				((MonoBehaviourPun)this).photonView.RPC("RPC_SetVoiceRangeAndFilters", (RpcTarget)0, new object[2] { 25, false });
				((MonoBehaviourPun)this).photonView.RPC("RPC_SetTalkingFlag", (RpcTarget)0, new object[2]
				{
					_localAvatar.photonView.ViewID,
					false
				});
				if ((Object)(object)_talkieLocal != (Object)null)
				{
					_talkieLocal.SetActive(false);
				}
			}

			private IEnumerator StopTalkingAfter(float delay)
			{
				_canToggle = false;
				yield return (object)new WaitForSeconds(delay);
				((MonoBehaviourPun)this).photonView.RPC("RPC_SetVoiceRangeAndFilters", (RpcTarget)0, new object[2] { 25, false });
				if ((Object)(object)_talkieLocal != (Object)null)
				{
					_talkieLocal.SetActive(false);
				}
				_canToggle = true;
			}

			private void TickBattery()
			{
				if (_usingRadio)
				{
					_battery -= Time.deltaTime * 5f;
					if (_battery <= 0f)
					{
						_battery = 0f;
						EndTalking();
					}
				}
				else if (_recharge)
				{
					_battery += Time.deltaTime * 1f;
					if (_battery > _maxBattery)
					{
						_battery = _maxBattery;
					}
				}
				if ((Object)(object)_batteryUi != (Object)null)
				{
					_batteryUi.Set(_battery, _maxBattery);
				}
			}

			private void TryCreateBatteryUi()
			{
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = GameObject.Find("Energy");
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)"[EMPRESS Walkie Talkies] Energy UI not found; skipping battery HUD.");
					}
					return;
				}
				GameObject val2 = Object.Instantiate<GameObject>(val, val.transform.parent);
				((Object)val2).name = "EMPRESSWalkieEnergy";
				Transform transform = val2.transform;
				transform.localPosition += new Vector3(0f, -33f, 0f);
				EnergyUI component = val2.GetComponent<EnergyUI>();
				if (Object.op_Implicit((Object)(object)component))
				{
					Object.DestroyImmediate((Object)(object)component);
				}
				TextMeshProUGUI[] componentsInChildren = val2.GetComponentsInChildren<TextMeshProUGUI>(true);
				foreach (TextMeshProUGUI val3 in componentsInChildren)
				{
					((Graphic)val3).color = _talkieColor;
				}
				Image componentInChildren = val2.GetComponentInChildren<Image>(true);
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					((Behaviour)componentInChildren).enabled = false;
				}
				_batteryUi = val2.AddComponent<WalkieBatteryUI>();
				_batteryUi.Tint(_talkieColor);
				_batteryUi.Set(_maxBattery, _maxBattery);
			}

			private void TryCreateLocalTalkie()
			{
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0123: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: 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)
				if ((Object)(object)_localParent == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)"[EMPRESS Walkie Talkies] Grabber Target or Local Camera not found; skipping local talkie mesh.");
					}
					return;
				}
				GameObject prefab = AssetLoader.GetPrefab("Talky", "walky");
				if ((Object)(object)prefab == (Object)null)
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogError((object)"[EMPRESS Walkie Talkies] Prefab not found in bundle. Place bundle beside the DLL. bundle=walky prefab=Talky");
					}
					return;
				}
				_talkieLocal = Object.Instantiate<GameObject>(prefab, _localParent);
				bool flag = string.Equals(((Object)_localParent).name, "Grabber Target", StringComparison.OrdinalIgnoreCase) || ((Object)_localParent).name.IndexOf("Grabber", StringComparison.OrdinalIgnoreCase) >= 0;
				float num = Mathf.Abs(CFG_RollDegrees.Value);
				Quaternion localRotation = Quaternion.AngleAxis(num, Vector3.forward);
				if (flag)
				{
					_talkieLocal.transform.localPosition = Vector3.zero;
					_talkieLocal.transform.localRotation = localRotation;
				}
				else
				{
					_talkieLocal.transform.localPosition = TalkiePos;
					_talkieLocal.transform.localRotation = TalkieRotation;
				}
				SetWorldScale(_talkieLocal.transform, CFG_WorldScale.Value);
				ApplyWalkieColor(_talkieLocal, _talkieColor);
				_talkieLocal.SetActive(false);
				_sfxOn = FindChildAudio(_talkieLocal, "OnSound");
				_sfxOff = FindChildAudio(_talkieLocal, "OffSound");
				_sfxIdle = FindChildAudio(_talkieLocal, "IdleOnSound");
				SetGoActive((Component?)(object)_sfxOn, active: false);
				SetGoActive((Component?)(object)_sfxOff, active: false);
				SetGoActive((Component?)(object)_sfxIdle, active: false);
			}

			[PunRPC]
			private void RPC_CreateRemoteTalkieOnRightArm(int ownerAvatarViewId)
			{
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Unknown result type (might be due to invalid IL or missing references)
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01db: Unknown result type (might be due to invalid IL or missing references)
				//IL_0197: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
				PlayerAvatar val = null;
				PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>();
				foreach (PlayerAvatar val2 in array)
				{
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2.photonView != (Object)null && val2.photonView.ViewID == ownerAvatarViewId)
					{
						val = val2;
						break;
					}
				}
				GameObject prefab = AssetLoader.GetPrefab("Talky", "walky");
				if ((Object)(object)prefab == (Object)null)
				{
					return;
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)$"[EMPRESS Walkie Talkies] Remote avatar ViewID {ownerAvatarViewId} not found; remote prop skipped.");
					}
					return;
				}
				Transform val3 = FindGrabberTarget(((Component)val).transform);
				float num = Mathf.Abs(CFG_RollDegrees.Value);
				Quaternion localRotation = Quaternion.AngleAxis(0f - num, Vector3.forward);
				if ((Object)(object)val3 != (Object)null)
				{
					_talkieRemote = Object.Instantiate<GameObject>(prefab, val3);
					_talkieRemote.transform.localPosition = Vector3.zero;
					_talkieRemote.transform.localRotation = localRotation;
				}
				else
				{
					PlayerAvatarRightArm val4 = (((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Component)((Component)val).transform.parent).GetComponentInChildren<PlayerAvatarRightArm>() : null);
					if ((Object)(object)val4 == (Object)null)
					{
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogWarning((object)"[EMPRESS Walkie Talkies] PlayerAvatarRightArm not found; remote prop skipped.");
						}
						return;
					}
					_talkieRemote = Object.Instantiate<GameObject>(prefab, val4.rightArmTransform);
					_talkieRemote.transform.localPosition = RemoteTalkiePos;
					_talkieRemote.transform.localRotation = RemoteTalkieRotation;
				}
				SetWorldScale(_talkieRemote.transform, CFG_WorldScale.Value);
				ApplyWalkieColor(_talkieRemote, _talkieColor);
				_talkieRemote.SetActive(false);
			}

			[PunRPC]
			private void RPC_ShowRemoteTalkie(bool show)
			{
				if ((Object)(object)_talkieRemote != (Object)null)
				{
					_talkieRemote.SetActive(show);
				}
			}

			[PunRPC]
			private void RPC_SetWalkieColor(int avatarViewId, float red, float green, float blue, string colorHex)
			{
				//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)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				_avatarViewId = avatarViewId;
				_talkieColor = new Color(Mathf.Clamp01(red), Mathf.Clamp01(green), Mathf.Clamp01(blue), 1f);
				_talkieColorHex = (string.IsNullOrWhiteSpace(colorHex) ? ("#" + ColorUtility.ToHtmlStringRGB(_talkieColor)) : colorHex);
				ApplyWalkieColor(_talkieLocal, _talkieColor);
				ApplyWalkieColor(_talkieRemote, _talkieColor);
				RecordClientColor(_avatarViewId, _talkieColorHex);
			}

			private void AnimateLocalArm()
			{
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_armRoot == (Object)null)
				{
					return;
				}
				Quaternion val = (_usingRadio ? Quaternion.Euler(0f, 0f, 0f) : Quaternion.Euler(70f, 0f, 0f));
				_armRoot.transform.localRotation = Quaternion.Lerp(_armRoot.transform.localRotation, val, Time.deltaTime * 10f);
				if (!_usingRadio && Quaternion.Angle(_armRoot.transform.localRotation, val) < 1f)
				{
					if (Object.op_Implicit((Object)(object)_talkieLocal) && _talkieLocal.activeSelf)
					{
						_talkieLocal.SetActive(false);
					}
				}
				else if (Object.op_Implicit((Object)(object)_talkieLocal) && !_talkieLocal.activeSelf)
				{
					_talkieLocal.SetActive(true);
				}
			}

			private void UpdateSfxVisibility()
			{
				float num = GetGameVolumeScalar() * 0.3f;
				if ((Object)(object)_sfxOn != (Object)null)
				{
					_sfxOn.volume = num * 0.5f;
				}
				if ((Object)(object)_sfxOff != (Object)null)
				{
					_sfxOff.volume = num * 0.5f;
				}
				if ((Object)(object)_sfxIdle != (Object)null)
				{
					_sfxIdle.volume = num;
				}
				if (_usingRadio)
				{
					SetGoActive((Component?)(object)_sfxOn, active: true);
					SetGoActive((Component?)(object)_sfxOff, active: false);
					SetGoActive((Component?)(object)_sfxIdle, active: true);
				}
				else
				{
					SetGoActive((Component?)(object)_sfxOn, active: false);
					SetGoActive((Component?)(object)_sfxOff, active: true);
					SetGoActive((Component?)(object)_sfxIdle, active: false);
				}
			}

			private float GetGameVolumeScalar()
			{
				float num = 1f;
				float num2 = 1f;
				try
				{
					num = 0.01f * (float)DataDirector.instance.SettingValueFetch((Setting)13);
					num2 = 0.01f * (float)DataDirector.instance.SettingValueFetch((Setting)1);
				}
				catch
				{
				}
				return Mathf.Clamp01(num * num2);
			}

			[PunRPC]
			private void RPC_SetVoiceRangeAndFilters(int maxDistance, bool talking)
			{
				AudioSource component = ((Component)this).GetComponent<AudioSource>();
				AudioLowPassLogic component2 = ((Component)this).GetComponent<AudioLowPassLogic>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.LogicActive = !talking;
					if (Object.op_Implicit((Object)(object)component2.AudioLowpassFilter))
					{
						component2.AudioLowpassFilter.cutoffFrequency = (talking ? component2.LowPassMax : 0f);
					}
				}
				AudioHighPassFilter val = ((Component)this).GetComponent<AudioHighPassFilter>() ?? ((Component)this).gameObject.AddComponent<AudioHighPassFilter>();
				val.cutoffFrequency = (talking ? 1000 : 10);
				if (Object.op_Implicit((Object)(object)component))
				{
					component.maxDistance = maxDistance;
				}
			}

			[PunRPC]
			private void RPC_SetTalkingFlag(int viewId, bool isTalking)
			{
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				if (isTalking)
				{
					PlayersTalking.Add(viewId);
					if (((MonoBehaviourPun)this).photonView.IsMine || !_enemiesHear)
					{
						return;
					}
					WalkieController[] array = Object.FindObjectsOfType<WalkieController>();
					foreach (WalkieController walkieController in array)
					{
						if (((MonoBehaviourPun)walkieController).photonView.IsMine && (Object)(object)walkieController._localAvatar != (Object)null)
						{
							try
							{
								EnemyDirector.instance.SetInvestigate(((Component)walkieController._localAvatar).transform.position + Vector3.up * 0.2f, 5f, false);
								break;
							}
							catch
							{
								break;
							}
						}
					}
				}
				else
				{
					PlayersTalking.Remove(viewId);
				}
			}

			[PunRPC]
			private void RPC_SyncSettings(int maxBattery, bool recharge, bool enemiesHear)
			{
				MaxBattery = maxBattery;
				Recharge = recharge;
				EnemiesHear = enemiesHear;
				_maxBattery = maxBattery;
				_recharge = recharge;
				_enemiesHear = enemiesHear;
				if (_battery > _maxBattery)
				{
					_battery = _maxBattery;
				}
				if (Object.op_Implicit((Object)(object)_batteryUi))
				{
					_batteryUi.Set(_battery, _maxBattery);
				}
			}

			[PunRPC]
			private void RPC_SetLocalAvatarViewId(int viewId)
			{
				_avatarViewId = viewId;
			}

			private static bool IsMasterOrSingle()
			{
				try
				{
					return SemiFunc.IsMasterClientOrSingleplayer();
				}
				catch
				{
					return PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom;
				}
			}

			private static bool IsInGame()
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Invalid comparison between Unknown and I4
				try
				{
					return (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2 && SemiFunc.RunIsLevel();
				}
				catch
				{
					return Object.FindObjectsOfType<PlayerAvatar>().Length != 0;
				}
			}

			private void TryResolveKey(string configured)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				if (Enum.TryParse<KeyCode>(configured, ignoreCase: true, out KeyCode result))
				{
					_pushKey = result;
				}
				else
				{
					_pushKey = (KeyCode)118;
				}
			}

			private static AudioSource? FindChildAudio(GameObject root, string childName)
			{
				if (!Object.op_Implicit((Object)(object)root))
				{
					return null;
				}
				Transform val = root.transform.Find(childName);
				return ((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<AudioSource>() : null;
			}

			private static void SetGoActive(Component? component, bool active)
			{
				if (!((Object)(object)component == (Object)null))
				{
					component.gameObject.SetActive(active);
				}
			}

			private static void SetWorldScale(Transform transform, float worldScale)
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)transform == (Object)null))
				{
					float num = Mathf.Clamp(worldScale, 0.001f, 5f);
					Transform parent = transform.parent;
					float num2 = (((Object)(object)parent != (Object)null) ? parent.lossyScale.x : 1f);
					float num3 = (((Object)(object)parent != (Object)null) ? parent.lossyScale.y : 1f);
					float num4 = (((Object)(object)parent != (Object)null) ? parent.lossyScale.z : 1f);
					if (Mathf.Approximately(num2, 0f))
					{
						num2 = 1f;
					}
					if (Mathf.Approximately(num3, 0f))
					{
						num3 = 1f;
					}
					if (Mathf.Approximately(num4, 0f))
					{
						num4 = 1f;
					}
					transform.localScale = new Vector3(num / num2, num / num3, num / num4);
				}
			}

			private static Transform? FindGrabberTarget(Transform avatarRoot)
			{
				if ((Object)(object)avatarRoot == (Object)null)
				{
					return null;
				}
				Transform val = avatarRoot.Find("[RIG]");
				Transform val2 = (((Object)(object)val != (Object)null) ? val.Find("Grabber Target") : null);
				return (Transform?)(((Object)(object)val2 != (Object)null) ? ((object)val2) : ((object)FindDeepChildByName(avatarRoot, "Grabber Target")));
			}

			private static Transform? FindDeepChildByName(Transform parent, string name)
			{
				if ((Object)(object)parent == (Object)null)
				{
					return null;
				}
				for (int i = 0; i < parent.childCount; i++)
				{
					Transform child = parent.GetChild(i);
					if (string.Equals(((Object)child).name, name, StringComparison.OrdinalIgnoreCase))
					{
						return child;
					}
					Transform val = FindDeepChildByName(child, name);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
				return null;
			}

			private static void ApplyWalkieColor(GameObject root, Color color)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Expected O, but got Unknown
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)root))
				{
					return;
				}
				RemoveColorBand(root);
				if (IsDefaultWalkieColor(color))
				{
					Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val in componentsInChildren)
					{
						val.SetPropertyBlock((MaterialPropertyBlock)null);
					}
					return;
				}
				Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val2 in componentsInChildren2)
				{
					MaterialPropertyBlock val3 = new MaterialPropertyBlock();
					val2.GetPropertyBlock(val3);
					val3.SetColor(ColorProperty, color);
					val3.SetColor(BaseColorProperty, color);
					val3.SetColor(AlbedoColorProperty, color);
					val3.SetColor(FresnelColorProperty, color);
					val3.SetColor(EmissionColorProperty, color * 0.35f);
					val2.SetPropertyBlock(val3);
				}
			}

			private static bool IsDefaultWalkieColor(Color color)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				Color val = ColorPresets["Empress"];
				return Mathf.Abs(color.r - val.r) < 0.002f && Mathf.Abs(color.g - val.g) < 0.002f && Mathf.Abs(color.b - val.b) < 0.002f;
			}

			private static void RemoveColorBand(GameObject root)
			{
				Transform val = root.transform.Find("EMPRESSWalkieColorBand");
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		public class WalkieBatteryUI : MonoBehaviour
		{
			private TextMeshProUGUI _current = null;

			private TextMeshProUGUI? _max;

			private void Awake()
			{
				_current = ((Component)this).GetComponent<TextMeshProUGUI>();
				Transform obj = ((Component)this).transform.Find("EnergyMax");
				_max = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			}

			public void Set(float value, float max)
			{
				if (Object.op_Implicit((Object)(object)_current))
				{
					((TMP_Text)_current).text = Mathf.Ceil(value).ToString();
				}
				if ((Object)(object)_max != (Object)null)
				{
					((TMP_Text)_max).text = "<b>/</b>" + Mathf.Ceil(max);
				}
			}

			public void Tint(Color color)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				TextMeshProUGUI[] componentsInChildren = ((Component)this).GetComponentsInChildren<TextMeshProUGUI>(true);
				foreach (TextMeshProUGUI val in componentsInChildren)
				{
					((Graphic)val).color = color;
				}
			}
		}

		internal static class AssetLoader
		{
			private static AssetBundle? _bundle;

			private static string? _loadedFor;

			public static GameObject? GetPrefab(string prefabName, string bundleBase)
			{
				if ((Object)(object)_bundle == (Object)null || _loadedFor != bundleBase)
				{
					TryLoadBundle(bundleBase);
				}
				if ((Object)(object)_bundle == (Object)null)
				{
					return null;
				}
				GameObject val = _bundle.LoadAsset<GameObject>(prefabName);
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)("[EMPRESS Walkie Talkies] Prefab '" + prefabName + "' not found in bundle '" + bundleBase + "'."));
					}
				}
				return val;
			}

			private static void TryLoadBundle(string baseName)
			{
				Unload();
				string[] array = new string[4]
				{
					Path.Combine(PluginDirectory, baseName),
					Path.Combine(PluginDirectory, baseName + ".assetbundle"),
					Path.Combine(PluginDirectory, baseName + ".unity3d"),
					Path.Combine(PluginDirectory, baseName + ".bundle")
				};
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (!File.Exists(text))
					{
						continue;
					}
					try
					{
						_bundle = AssetBundle.LoadFromFile(text);
						if ((Object)(object)_bundle != (Object)null)
						{
							_loadedFor = baseName;
							return;
						}
					}
					catch (Exception arg)
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogWarning((object)$"[EMPRESS Walkie Talkies] Failed to load bundle '{text}': {arg}");
						}
					}
				}
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogError((object)("[EMPRESS Walkie Talkies] Could not find bundle '" + baseName + "' beside the DLL."));
				}
			}

			public static void Unload()
			{
				if ((Object)(object)_bundle != (Object)null)
				{
					try
					{
						_bundle.Unload(false);
					}
					catch
					{
					}
				}
				_bundle = null;
				_loadedFor = null;
			}
		}

		public const string PluginGuid = "empress.repo.walkietalkies";

		public const string PluginName = "EMPRESS Walkie Talkies";

		public const string PluginVersion = "1.3.0";

		internal static ManualLogSource Log = null;

		internal static string PluginDirectory = string.Empty;

		internal static ConfigEntry<string> CFG_TalkKey = null;

		internal static ConfigEntry<int> CFG_MaxBattery = null;

		internal static ConfigEntry<bool> CFG_Recharge = null;

		internal static ConfigEntry<bool> CFG_EnemiesHear = null;

		internal static ConfigEntry<string> CFG_WalkieColor = null;

		internal static ConfigEntry<bool> CFG_LogClientColors = null;

		internal static ConfigEntry<float> CFG_WorldScale = null;

		internal static ConfigEntry<float> CFG_RollDegrees = null;

		internal static int MaxBattery = 40;

		internal static bool Recharge = true;

		internal static bool EnemiesHear = true;

		internal static Color LocalColor = new Color(0.87f, 0.69f, 1f, 1f);

		internal static string LocalColorHex = "#DDB0FF";

		private const string DefaultColorPreset = "Empress";

		private const string ColorBandName = "EMPRESSWalkieColorBand";

		private static readonly Dictionary<string, Color> ColorPresets = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase)
		{
			{
				"Empress",
				new Color(0.87f, 0.69f, 1f, 1f)
			},
			{
				"Red",
				new Color(1f, 0.16f, 0.16f, 1f)
			},
			{
				"Orange",
				new Color(1f, 0.48f, 0.12f, 1f)
			},
			{
				"Yellow",
				new Color(1f, 0.86f, 0.18f, 1f)
			},
			{
				"Green",
				new Color(0.2f, 0.95f, 0.38f, 1f)
			},
			{
				"Cyan",
				new Color(0.18f, 0.9f, 1f, 1f)
			},
			{
				"Blue",
				new Color(0.25f, 0.48f, 1f, 1f)
			},
			{
				"Purple",
				new Color(0.65f, 0.28f, 1f, 1f)
			},
			{
				"Pink",
				new Color(1f, 0.34f, 0.78f, 1f)
			},
			{
				"White",
				new Color(0.95f, 0.95f, 0.95f, 1f)
			},
			{
				"Black",
				new Color(0.02f, 0.02f, 0.025f, 1f)
			}
		};

		private static readonly Dictionary<int, string> ClientColors = new Dictionary<int, string>();

		private Harmony _harmony = null;

		private void Awake()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath;
			CFG_TalkKey = ((BaseUnityPlugin)this).Config.Bind<string>("Controls", "PushToTalkKey", "V", "Key to hold for radio talk. Example: V, F, Mouse4, LeftShift");
			CFG_MaxBattery = ((BaseUnityPlugin)this).Config.Bind<int>("Battery (host only)", "MaxBattery", 40, new ConfigDescription("Walkie battery capacity.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 200), Array.Empty<object>()));
			CFG_Recharge = ((BaseUnityPlugin)this).Config.Bind<bool>("Battery (host only)", "RechargeDuringLevel", true, "Recharge slowly when not transmitting.");
			CFG_EnemiesHear = ((BaseUnityPlugin)this).Config.Bind<bool>("Enemies (host only)", "EnemiesHearRadio", true, "If true, enemy AI will get an investigate ping when a player transmits.");
			CFG_WalkieColor = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "WalkieColor", "Empress", new ConfigDescription("Local walkie color preset.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[11]
			{
				"Empress", "Red", "Orange", "Yellow", "Green", "Cyan", "Blue", "Purple", "Pink", "White",
				"Black"
			}), Array.Empty<object>()));
			CFG_LogClientColors = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "LogClientColors", false, "When true, logs client walkie colors once per changed sync.");
			CFG_WorldScale = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "WorldScale", 0.05f, new ConfigDescription("World size of the radio model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.005f, 1f), Array.Empty<object>()));
			CFG_RollDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "RollDegrees", 0f, new ConfigDescription("Roll degrees for the radio model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 45f), Array.Empty<object>()));
			MaxBattery = CFG_MaxBattery.Value;
			Recharge = CFG_Recharge.Value;
			EnemiesHear = CFG_EnemiesHear.Value;
			RefreshLocalColor();
			CFG_WalkieColor.SettingChanged += OnAppearanceConfigChanged;
			CFG_LogClientColors.SettingChanged += OnAppearanceConfigChanged;
			_harmony = new Harmony("empress.repo.walkietalkies");
			_harmony.PatchAll(typeof(Patch_AttachController));
			_harmony.PatchAll(typeof(Patch_RightArmPose));
		}

		private static void OnAppearanceConfigChanged(object sender, EventArgs args)
		{
			RefreshLocalColor();
			WalkieController[] array = Object.FindObjectsOfType<WalkieController>();
			foreach (WalkieController walkieController in array)
			{
				if ((Object)(object)walkieController != (Object)null && (Object)(object)((MonoBehaviourPun)walkieController).photonView != (Object)null && ((MonoBehaviourPun)walkieController).photonView.IsMine)
				{
					walkieController.PublishLocalColor();
				}
			}
		}

		private static void RefreshLocalColor()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (TryParseConfiguredColor(CFG_WalkieColor.Value, out Color color, out string hex))
			{
				LocalColor = color;
				LocalColorHex = hex;
				return;
			}
			LocalColor = new Color(0.87f, 0.69f, 1f, 1f);
			LocalColorHex = "#DDB0FF";
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)("[EMPRESS Walkie Talkies] Invalid WalkieColor '" + CFG_WalkieColor.Value + "', using Empress."));
			}
		}

		private static bool TryParseConfiguredColor(string configured, out Color color, out string hex)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			color = new Color(0.87f, 0.69f, 1f, 1f);
			hex = "#DDB0FF";
			if (string.IsNullOrWhiteSpace(configured))
			{
				return false;
			}
			string text = configured.Trim();
			if (ColorPresets.TryGetValue(text, out var value))
			{
				color = value;
				hex = "#" + ColorUtility.ToHtmlStringRGB(value);
				return true;
			}
			string text2 = text;
			if (!text2.StartsWith("#", StringComparison.Ordinal) && IsHexColor(text2))
			{
				text2 = "#" + text2;
			}
			Color val = default(Color);
			if (ColorUtility.TryParseHtmlString(text2, ref val))
			{
				val.a = 1f;
				color = val;
				hex = "#" + ColorUtility.ToHtmlStringRGB(val);
				return true;
			}
			string[] array = text.Split(new char[2] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length != 3 && array.Length != 4)
			{
				return false;
			}
			if (!TryParseFloat(array[0], out var result) || !TryParseFloat(array[1], out var result2) || !TryParseFloat(array[2], out var result3))
			{
				return false;
			}
			if (result > 1f || result2 > 1f || result3 > 1f)
			{
				result /= 255f;
				result2 /= 255f;
				result3 /= 255f;
			}
			color = new Color(Mathf.Clamp01(result), Mathf.Clamp01(result2), Mathf.Clamp01(result3), 1f);
			hex = "#" + ColorUtility.ToHtmlStringRGB(color);
			return true;
		}

		private static bool IsHexColor(string value)
		{
			if (value.Length != 6 && value.Length != 8)
			{
				return false;
			}
			foreach (char character in value)
			{
				if (!Uri.IsHexDigit(character))
				{
					return false;
				}
			}
			return true;
		}

		private static bool TryParseFloat(string value, out float result)
		{
			return float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out result);
		}

		internal static void RecordClientColor(int avatarViewId, string colorHex)
		{
			if (avatarViewId <= 0 || string.IsNullOrWhiteSpace(colorHex) || (ClientColors.TryGetValue(avatarViewId, out string value) && string.Equals(value, colorHex, StringComparison.OrdinalIgnoreCase)))
			{
				return;
			}
			ClientColors[avatarViewId] = colorHex;
			if (CFG_LogClientColors.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogMessage((object)("[EMPRESS Walkie Talkies] " + GetPlayerLabel(avatarViewId) + " walkie color " + colorHex + "."));
				}
			}
		}

		private static string GetPlayerLabel(int avatarViewId)
		{
			PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>();
			foreach (PlayerAvatar val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.photonView != (Object)null && val.photonView.ViewID == avatarViewId)
				{
					return string.IsNullOrWhiteSpace(val.playerName) ? $"ViewID {avatarViewId}" : val.playerName;
				}
			}
			return $"ViewID {avatarViewId}";
		}
	}
}