Decompiled source of EvenMoreSkinColors v0.1.3

EvenMoreSkinColors.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("EvenMoreSkinColors")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EvenMoreSkinColors")]
[assembly: AssemblyTitle("EvenMoreSkinColors")]
[assembly: AssemblyVersion("1.0.0.0")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EvenMoreSkinColors
{
	internal static class Compatibility
	{
		internal static bool IsMoreSkinColorsPresent { get; private set; }

		internal static void DetectInstalledMods()
		{
			IsMoreSkinColorsPresent = Chainloader.PluginInfos.Values.Any(delegate(PluginInfo info)
			{
				string text = info.Metadata.GUID ?? string.Empty;
				string text2 = info.Metadata.Name ?? string.Empty;
				return text.Equals("ViViKo.MoreSkinColors", StringComparison.OrdinalIgnoreCase) || text2.Equals("MoreSkinColors", StringComparison.OrdinalIgnoreCase) || text.IndexOf("MoreSkinColors", StringComparison.OrdinalIgnoreCase) >= 0;
			});
			if (IsMoreSkinColorsPresent)
			{
				Plugin.Log.LogInfo((object)"Compatibility mode active: detected MoreSkinColors. Vanilla swatches remain untouched; custom tone UI stays additive.");
			}
		}
	}
	public static class DebugApi
	{
		public sealed class LocalState
		{
			public bool hasLocalPlayer;

			public uint localNetId;

			public int activeLoadoutIndex;

			public int vanillaSkinColorIndex;

			public bool customToneEnabled;

			public string customColorHex;

			public bool previewOverrideApplied;

			public bool playerOverrideApplied;

			public string lastEvent;
		}

		public sealed class RemoteState
		{
			public uint netId;

			public bool isLocalPlayer;

			public int vanillaSkinColorIndex;

			public bool hasCustomTone;

			public string customColorHex;

			public bool overrideApplied;
		}

		public sealed class Snapshot
		{
			public LocalState local;

			public List<RemoteState> players;
		}

		public static LocalState GetLocalState()
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
			PlayerCosmetics val = (((Object)(object)localPlayerInfo != (Object)null) ? localPlayerInfo.Cosmetics : null);
			PlayerCosmeticsSwitcher val2 = (((Object)(object)SingletonBehaviour<PlayerCustomizationMenu>.Instance != (Object)null && (Object)(object)SingletonBehaviour<PlayerCustomizationMenu>.Instance.characterPreview != (Object)null) ? SingletonBehaviour<PlayerCustomizationMenu>.Instance.characterPreview.cosmeticsSwitcher : null);
			return new LocalState
			{
				hasLocalPlayer = ((Object)(object)localPlayerInfo != (Object)null),
				localNetId = (((Object)(object)val != (Object)null) ? ((NetworkBehaviour)val).netId : 0u),
				activeLoadoutIndex = SkinToneState.ActiveLoadoutIndex,
				vanillaSkinColorIndex = (((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<PlayerCosmeticsSwitcher>() != (Object)null) ? ((Component)val).GetComponent<PlayerCosmeticsSwitcher>().CurrentSkinColorIndex : (-1)),
				customToneEnabled = SkinToneState.LocalSelection.Enabled,
				customColorHex = SkinToneSelection.ToHtml(SkinToneState.LocalSelection.BaseColor),
				previewOverrideApplied = ((Object)(object)val2 != (Object)null && SkinToneState.LocalSelection.Enabled),
				playerOverrideApplied = ((Object)(object)val != (Object)null && SkinToneState.LocalSelection.Enabled),
				lastEvent = SkinToneDebugState.Current.LastEvent
			};
		}

		public static List<RemoteState> GetRemoteStates()
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			List<RemoteState> list = new List<RemoteState>();
			foreach (KeyValuePair<uint, NetworkIdentity> item in NetworkClient.spawned)
			{
				NetworkIdentity value = item.Value;
				if (!((Object)(object)value == (Object)null))
				{
					PlayerCosmetics val = ((Component)value).GetComponent<PlayerCosmetics>();
					if ((Object)(object)val == (Object)null)
					{
						PlayerInfo component = ((Component)value).GetComponent<PlayerInfo>();
						val = (((Object)(object)component != (Object)null) ? component.Cosmetics : null);
					}
					if (!((Object)(object)val == (Object)null))
					{
						PlayerCosmeticsSwitcher component2 = ((Component)val).GetComponent<PlayerCosmeticsSwitcher>();
						SkinToneSelection selection;
						bool flag = SkinToneState.TryGetRemoteSelection(((NetworkBehaviour)val).netId, out selection);
						list.Add(new RemoteState
						{
							netId = ((NetworkBehaviour)val).netId,
							isLocalPlayer = ((NetworkBehaviour)val).isLocalPlayer,
							vanillaSkinColorIndex = (((Object)(object)component2 != (Object)null) ? component2.CurrentSkinColorIndex : (-1)),
							hasCustomTone = (((NetworkBehaviour)val).isLocalPlayer ? SkinToneState.LocalSelection.Enabled : (flag && selection.Enabled)),
							customColorHex = (((NetworkBehaviour)val).isLocalPlayer ? SkinToneSelection.ToHtml(SkinToneState.LocalSelection.BaseColor) : (flag ? SkinToneSelection.ToHtml(selection.BaseColor) : string.Empty)),
							overrideApplied = (((NetworkBehaviour)val).isLocalPlayer ? SkinToneState.LocalSelection.Enabled : (flag && selection.Enabled))
						});
					}
				}
			}
			return list;
		}

		public static Snapshot GetSnapshot()
		{
			return new Snapshot
			{
				local = GetLocalState(),
				players = GetRemoteStates()
			};
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(PlayerCosmetics), "Awake")]
		[HarmonyPostfix]
		private static void PlayerCosmeticsAwakePostfix(PlayerCosmetics __instance)
		{
			SkinToneFollower skinToneFollower = ((Component)__instance).GetComponent<SkinToneFollower>();
			if ((Object)(object)skinToneFollower == (Object)null)
			{
				skinToneFollower = ((Component)__instance).gameObject.AddComponent<SkinToneFollower>();
			}
			skinToneFollower.Initialize(__instance);
		}

		[HarmonyPatch(typeof(PlayerCosmetics), "OnStartLocalPlayer")]
		[HarmonyPostfix]
		private static void PlayerCosmeticsOnStartLocalPlayerPostfix(PlayerCosmetics __instance)
		{
			SkinToneState.OnLocalPlayerStarted(__instance);
		}

		[HarmonyPatch(typeof(PlayerCosmeticsSwitcher), "SetSkinColor")]
		[HarmonyPostfix]
		private static void PlayerCosmeticsSwitcherSetSkinColorPostfix(PlayerCosmeticsSwitcher __instance)
		{
			if (!SkinToneState.IsRevertingToVanilla)
			{
				PlayerCosmetics component = ((Component)__instance).GetComponent<PlayerCosmetics>();
				if ((Object)(object)component != (Object)null)
				{
					SkinToneState.TryApplyFor(component);
				}
				else if ((Object)(object)SingletonBehaviour<PlayerCustomizationMenu>.Instance != (Object)null && (Object)(object)SingletonBehaviour<PlayerCustomizationMenu>.Instance.characterPreview != (Object)null && SingletonBehaviour<PlayerCustomizationMenu>.Instance.characterPreview.cosmeticsSwitcher == __instance)
				{
					SkinToneState.ApplyToPreview(SingletonBehaviour<PlayerCustomizationMenu>.Instance);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerCustomizationMenu), "Start")]
		[HarmonyPostfix]
		private static void PlayerCustomizationMenuStartPostfix(PlayerCustomizationMenu __instance)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance.skinColorTemplate == (Object)null || (Object)(object)__instance.skinColorTemplate.transform.parent == (Object)null)
			{
				return;
			}
			Transform val = null;
			if ((Object)(object)__instance.characterPreview != (Object)null)
			{
				val = ((Component)__instance.characterPreview).transform;
			}
			if ((Object)(object)val == (Object)null)
			{
				Transform parent = __instance.skinColorTemplate.transform.parent;
				val = (((Object)(object)parent.parent != (Object)null) ? parent.parent : parent);
			}
			if ((Object)(object)val.Find("EvenMoreSkinColors_CustomSkinTonePanel") != (Object)null)
			{
				return;
			}
			foreach (Transform item in ((Object)(object)val.parent != (Object)null) ? val.parent : val)
			{
				Transform val2 = item.Find("EvenMoreSkinColors_CustomSkinTonePanel");
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.parent != (Object)(object)val)
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
			}
			GameObject val3 = new GameObject("EvenMoreSkinColors_CustomSkinTonePanel");
			val3.transform.SetParent(val, false);
			val3.transform.SetAsLastSibling();
			val3.AddComponent<SkinTonePickerPanel>().Initialize(__instance);
			SkinToneState.ApplyToPreview(__instance);
		}

		[HarmonyPatch(typeof(PlayerCustomizationMenu), "SetLoadout")]
		[HarmonyPostfix]
		private static void PlayerCustomizationMenuSetLoadoutPostfix(int index)
		{
			SkinToneState.ActivateLoadout(index, applyPreview: true, broadcast: false);
		}

		[HarmonyPatch(typeof(PlayerCustomizationMenu), "SetSkinColorIndex")]
		[HarmonyPostfix]
		private static void PlayerCustomizationMenuSetSkinColorIndexPostfix(PlayerCustomizationMenu __instance)
		{
			SkinToneState.ApplyToPreview(__instance);
		}

		[HarmonyPatch(typeof(PlayerCustomizationMenu), "SaveLoadout")]
		[HarmonyPostfix]
		private static void PlayerCustomizationMenuSaveLoadoutPostfix()
		{
			SkinToneState.ActivateLoadout(SkinToneState.ActiveLoadoutIndex, applyPreview: true, broadcast: true);
		}
	}
	[BepInPlugin("cray.evenmoreskincolors", "EvenMoreSkinColors", "0.1.3")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "cray.evenmoreskincolors";

		public const string ModName = "EvenMoreSkinColors";

		public const string ModVersion = "0.1.3";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Compatibility.DetectInstalledMods();
			SkinToneState.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			SkinToneNetworkSerialization.Register();
			NetworkClient.OnConnectedEvent = (Action)Delegate.Combine(NetworkClient.OnConnectedEvent, new Action(SkinToneNetwork.OnClientConnected));
			new Harmony("cray.evenmoreskincolors").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"EvenMoreSkinColors v0.1.3 loaded.");
		}

		private void OnDestroy()
		{
			NetworkClient.OnConnectedEvent = (Action)Delegate.Remove(NetworkClient.OnConnectedEvent, new Action(SkinToneNetwork.OnClientConnected));
		}
	}
	internal static class SkinToneDebugState
	{
		internal struct Snapshot
		{
			public int ActiveLoadoutIndex;

			public bool LocalCustomToneEnabled;

			public string LocalColorHex;

			public uint LastAppliedNetId;

			public bool LastAppliedWasPreview;

			public string LastAppliedColorHex;

			public uint LastBroadcastNetId;

			public string LastBroadcastColorHex;

			public uint LastReceivedNetId;

			public string LastReceivedColorHex;

			public string LastEvent;
		}

		private static Snapshot _snapshot;

		internal static Snapshot Current => _snapshot;

		internal static void RecordLoadoutActivated(int loadoutIndex, SkinToneSelection selection)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			_snapshot.ActiveLoadoutIndex = loadoutIndex;
			_snapshot.LocalCustomToneEnabled = selection.Enabled;
			_snapshot.LocalColorHex = SkinToneSelection.ToHtml(selection.BaseColor);
			_snapshot.LastEvent = $"loadout:{loadoutIndex}";
		}

		internal static void RecordSelectionChanged(int loadoutIndex, SkinToneSelection selection)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			_snapshot.ActiveLoadoutIndex = loadoutIndex;
			_snapshot.LocalCustomToneEnabled = selection.Enabled;
			_snapshot.LocalColorHex = SkinToneSelection.ToHtml(selection.BaseColor);
			_snapshot.LastEvent = $"selection:{loadoutIndex}";
		}

		internal static void RecordBroadcast(uint netId, SkinToneSelection selection)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			_snapshot.LastBroadcastNetId = netId;
			_snapshot.LastBroadcastColorHex = SkinToneSelection.ToHtml(selection.BaseColor);
			_snapshot.LastEvent = $"broadcast:{netId}";
			Plugin.Log.LogInfo((object)$"EMSC_DEBUG broadcast netId={netId} enabled={selection.Enabled} color={_snapshot.LastBroadcastColorHex}");
		}

		internal static void RecordReceive(uint netId, SkinToneSelection selection)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			_snapshot.LastReceivedNetId = netId;
			_snapshot.LastReceivedColorHex = SkinToneSelection.ToHtml(selection.BaseColor);
			_snapshot.LastEvent = $"receive:{netId}";
			Plugin.Log.LogInfo((object)$"EMSC_DEBUG receive netId={netId} enabled={selection.Enabled} color={_snapshot.LastReceivedColorHex}");
		}

		internal static void RecordApplyPreview(SkinToneSelection selection)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			_snapshot.LastAppliedNetId = 0u;
			_snapshot.LastAppliedWasPreview = true;
			_snapshot.LastAppliedColorHex = SkinToneSelection.ToHtml(selection.BaseColor);
			_snapshot.LastEvent = "apply-preview";
			Plugin.Log.LogInfo((object)$"EMSC_DEBUG apply preview enabled={selection.Enabled} color={_snapshot.LastAppliedColorHex}");
		}

		internal static void RecordApplyPlayer(uint netId, SkinToneSelection selection)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			_snapshot.LastAppliedNetId = netId;
			_snapshot.LastAppliedWasPreview = false;
			_snapshot.LastAppliedColorHex = SkinToneSelection.ToHtml(selection.BaseColor);
			_snapshot.LastEvent = $"apply-player:{netId}";
			Plugin.Log.LogInfo((object)$"EMSC_DEBUG apply player netId={netId} enabled={selection.Enabled} color={_snapshot.LastAppliedColorHex}");
		}

		internal static void RecordRevert(uint netId, bool isPreview)
		{
			_snapshot.LastAppliedNetId = netId;
			_snapshot.LastAppliedWasPreview = isPreview;
			_snapshot.LastEvent = (isPreview ? "revert-preview" : $"revert-player:{netId}");
			Plugin.Log.LogInfo((object)("EMSC_DEBUG revert " + (isPreview ? "preview" : $"player netId={netId}")));
		}
	}
	internal sealed class SkinToneFollower : MonoBehaviour
	{
		private PlayerCosmetics _cosmetics;

		private bool _hasLastApplied;

		private SkinToneSelection _lastApplied;

		internal void Initialize(PlayerCosmetics cosmetics)
		{
			_cosmetics = cosmetics;
		}

		private void Update()
		{
			if ((Object)(object)_cosmetics == (Object)null || (Object)(object)((Component)_cosmetics).GetComponent<PlayerCosmeticsSwitcher>() == (Object)null || ((NetworkBehaviour)_cosmetics).netId == 0)
			{
				return;
			}
			SkinToneSelection selection;
			if (((NetworkBehaviour)_cosmetics).isLocalPlayer)
			{
				SkinToneSelection localSelection = SkinToneState.LocalSelection;
				if (!_hasLastApplied || !_lastApplied.Equals(localSelection))
				{
					_hasLastApplied = true;
					_lastApplied = localSelection;
					SkinToneState.TryApplyFor(_cosmetics);
				}
			}
			else if (SkinToneState.TryGetRemoteSelection(((NetworkBehaviour)_cosmetics).netId, out selection))
			{
				if (!_hasLastApplied || !_lastApplied.Equals(selection))
				{
					_hasLastApplied = true;
					_lastApplied = selection;
					SkinToneState.TryApplyFor(_cosmetics);
				}
			}
			else if (_hasLastApplied)
			{
				_hasLastApplied = false;
				SkinToneState.RevertToVanilla(((Component)_cosmetics).GetComponent<PlayerCosmeticsSwitcher>());
			}
		}
	}
	internal static class SkinToneMaterialApplier
	{
		internal static void Apply(PlayerCosmeticsSwitcher switcher, SkinToneSelection selection)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)switcher == (Object)null || !selection.Enabled)
			{
				return;
			}
			Traverse obj = Traverse.Create((object)switcher);
			MaterialPropertyBlock val = (MaterialPropertyBlock)(((object)obj.Field<MaterialPropertyBlock>("skinColorProps").Value) ?? ((object)new MaterialPropertyBlock()));
			obj.Field("skinColorProps").SetValue((object)val);
			ApplyColor(obj.Field<Renderer>("headRenderer").Value, val, selection.BaseColor);
			ApplyColor(obj.Field<Renderer>("bodyRenderer").Value, val, selection.BaseColor);
			ApplyColor(obj.Field<Renderer>("mouthRenderer").Value, val, selection.MouthColor);
			object value = obj.Field("currentHeadModel").GetValue();
			if (value == null)
			{
				return;
			}
			object value2 = Traverse.Create(value).Field("cosmetic").GetValue();
			if (value2 == null)
			{
				return;
			}
			bool value3 = Traverse.Create(value2).Field("requireSkinColorTint").GetValue<bool>();
			int value4 = Traverse.Create(value2).Field("skinColorTintMaterialIndex").GetValue<int>();
			if (!value3)
			{
				return;
			}
			Component val2 = (Component)((value2 is Component) ? value2 : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				val3.GetPropertyBlock(val);
				val.SetColor("_Color", selection.BaseColor);
				if (value4 < 0)
				{
					val3.SetPropertyBlock(val);
				}
				else
				{
					val3.SetPropertyBlock(val, value4);
				}
			}
		}

		private static void ApplyColor(Renderer renderer, MaterialPropertyBlock propertyBlock, Color color)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)renderer == (Object)null))
			{
				renderer.GetPropertyBlock(propertyBlock);
				propertyBlock.SetColor("_Color", color);
				renderer.SetPropertyBlock(propertyBlock);
			}
		}
	}
	public struct SkinToneUpdateRequestMsg : NetworkMessage
	{
		public bool enabled;

		public byte r;

		public byte g;

		public byte b;
	}
	public struct SkinToneStateMsg : NetworkMessage
	{
		public uint netId;

		public bool enabled;

		public byte r;

		public byte g;

		public byte b;
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct SkinToneSnapshotRequestMsg : NetworkMessage
	{
	}
	internal static class SkinToneNetwork
	{
		private static bool _clientHandlersRegistered;

		private static bool _serverHandlersRegistered;

		private static readonly Dictionary<uint, SkinToneSelection> ServerSelections = new Dictionary<uint, SkinToneSelection>();

		internal static void OnClientConnected()
		{
			RegisterClientHandlers();
			RegisterServerHandlers();
			if (NetworkClient.active)
			{
				NetworkClient.Send<SkinToneSnapshotRequestMsg>(default(SkinToneSnapshotRequestMsg), 0);
			}
		}

		internal static void TryBroadcastLocalSelection(SkinToneSelection selection)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkClient.active)
			{
				RegisterClientHandlers();
				RegisterServerHandlers();
				Color32 val = Color32.op_Implicit(selection.BaseColor);
				SkinToneDebugState.RecordBroadcast((NetworkClient.connection != null && (Object)(object)((NetworkConnection)NetworkClient.connection).identity != (Object)null) ? ((NetworkConnection)NetworkClient.connection).identity.netId : 0u, selection);
				SkinToneUpdateRequestMsg skinToneUpdateRequestMsg = default(SkinToneUpdateRequestMsg);
				skinToneUpdateRequestMsg.enabled = selection.Enabled;
				skinToneUpdateRequestMsg.r = val.r;
				skinToneUpdateRequestMsg.g = val.g;
				skinToneUpdateRequestMsg.b = val.b;
				NetworkClient.Send<SkinToneUpdateRequestMsg>(skinToneUpdateRequestMsg, 0);
			}
		}

		private static void RegisterClientHandlers()
		{
			if (!_clientHandlersRegistered)
			{
				NetworkClient.ReplaceHandler<SkinToneStateMsg>((Action<SkinToneStateMsg>)OnStateMessage, true);
				_clientHandlersRegistered = true;
			}
		}

		private static void RegisterServerHandlers()
		{
			if (NetworkServer.active && !_serverHandlersRegistered)
			{
				NetworkServer.ReplaceHandler<SkinToneUpdateRequestMsg>((Action<NetworkConnectionToClient, SkinToneUpdateRequestMsg>)OnUpdateRequest, true);
				NetworkServer.ReplaceHandler<SkinToneSnapshotRequestMsg>((Action<NetworkConnectionToClient, SkinToneSnapshotRequestMsg>)OnSnapshotRequest, true);
				_serverHandlersRegistered = true;
			}
		}

		private static void OnStateMessage(SkinToneStateMsg msg)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			SkinToneSelection skinToneSelection = default(SkinToneSelection);
			skinToneSelection.Enabled = msg.enabled;
			skinToneSelection.BaseColor = Color32.op_Implicit(new Color32(msg.r, msg.g, msg.b, byte.MaxValue));
			SkinToneSelection selection = skinToneSelection;
			SkinToneDebugState.RecordReceive(msg.netId, selection);
			if (selection.Enabled)
			{
				SkinToneState.SetRemoteSelection(msg.netId, selection);
			}
			else
			{
				SkinToneState.ClearRemoteSelection(msg.netId);
			}
		}

		private static void OnUpdateRequest(NetworkConnectionToClient conn, SkinToneUpdateRequestMsg msg)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (conn == null || (Object)(object)((NetworkConnection)conn).identity == (Object)null)
			{
				return;
			}
			PlayerCosmetics val = ((Component)((NetworkConnection)conn).identity).GetComponent<PlayerCosmetics>();
			if ((Object)(object)val == (Object)null)
			{
				PlayerInfo component = ((Component)((NetworkConnection)conn).identity).GetComponent<PlayerInfo>();
				val = (((Object)(object)component != (Object)null) ? component.Cosmetics : null);
			}
			if (!((Object)(object)val == (Object)null))
			{
				SkinToneSelection skinToneSelection = default(SkinToneSelection);
				skinToneSelection.Enabled = msg.enabled;
				skinToneSelection.BaseColor = Color32.op_Implicit(new Color32(msg.r, msg.g, msg.b, byte.MaxValue));
				SkinToneSelection skinToneSelection2 = skinToneSelection;
				if (skinToneSelection2.Enabled)
				{
					ServerSelections[((NetworkBehaviour)val).netId] = skinToneSelection2;
				}
				else
				{
					ServerSelections.Remove(((NetworkBehaviour)val).netId);
				}
				NetworkServer.SendToAll<SkinToneStateMsg>(BuildState(((NetworkBehaviour)val).netId, skinToneSelection2), 0, false);
			}
		}

		private static void OnSnapshotRequest(NetworkConnectionToClient conn, SkinToneSnapshotRequestMsg _)
		{
			if (conn == null)
			{
				return;
			}
			foreach (KeyValuePair<uint, SkinToneSelection> serverSelection in ServerSelections)
			{
				((NetworkConnection)conn).Send<SkinToneStateMsg>(BuildState(serverSelection.Key, serverSelection.Value), 0);
			}
		}

		private static SkinToneStateMsg BuildState(uint netId, SkinToneSelection selection)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Color32 val = Color32.op_Implicit(selection.BaseColor);
			SkinToneStateMsg result = default(SkinToneStateMsg);
			result.netId = netId;
			result.enabled = selection.Enabled;
			result.r = val.r;
			result.g = val.g;
			result.b = val.b;
			return result;
		}
	}
	internal static class SkinToneNetworkSerialization
	{
		internal static void Register()
		{
			Writer<SkinToneUpdateRequestMsg>.write = WriteSkinToneUpdateRequest;
			Reader<SkinToneUpdateRequestMsg>.read = ReadSkinToneUpdateRequest;
			Writer<SkinToneStateMsg>.write = WriteSkinToneState;
			Reader<SkinToneStateMsg>.read = ReadSkinToneState;
			Writer<SkinToneSnapshotRequestMsg>.write = WriteSkinToneSnapshotRequest;
			Reader<SkinToneSnapshotRequestMsg>.read = ReadSkinToneSnapshotRequest;
		}

		private static void WriteSkinToneUpdateRequest(NetworkWriter writer, SkinToneUpdateRequestMsg msg)
		{
			NetworkWriterExtensions.WriteBool(writer, msg.enabled);
			writer.WriteByte(msg.r);
			writer.WriteByte(msg.g);
			writer.WriteByte(msg.b);
		}

		private static SkinToneUpdateRequestMsg ReadSkinToneUpdateRequest(NetworkReader reader)
		{
			SkinToneUpdateRequestMsg result = default(SkinToneUpdateRequestMsg);
			result.enabled = NetworkReaderExtensions.ReadBool(reader);
			result.r = reader.ReadByte();
			result.g = reader.ReadByte();
			result.b = reader.ReadByte();
			return result;
		}

		private static void WriteSkinToneState(NetworkWriter writer, SkinToneStateMsg msg)
		{
			NetworkWriterExtensions.WriteUInt(writer, msg.netId);
			NetworkWriterExtensions.WriteBool(writer, msg.enabled);
			writer.WriteByte(msg.r);
			writer.WriteByte(msg.g);
			writer.WriteByte(msg.b);
		}

		private static SkinToneStateMsg ReadSkinToneState(NetworkReader reader)
		{
			SkinToneStateMsg result = default(SkinToneStateMsg);
			result.netId = NetworkReaderExtensions.ReadUInt(reader);
			result.enabled = NetworkReaderExtensions.ReadBool(reader);
			result.r = reader.ReadByte();
			result.g = reader.ReadByte();
			result.b = reader.ReadByte();
			return result;
		}

		private static void WriteSkinToneSnapshotRequest(NetworkWriter writer, SkinToneSnapshotRequestMsg msg)
		{
		}

		private static SkinToneSnapshotRequestMsg ReadSkinToneSnapshotRequest(NetworkReader reader)
		{
			return default(SkinToneSnapshotRequestMsg);
		}
	}
	internal sealed class SkinTonePickerPanel : MonoBehaviour
	{
		private sealed class ColorDragSurface : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IDragHandler, IPointerUpHandler, IEndDragHandler
		{
			internal Action<Vector2, RectTransform> Handler;

			internal Action EndHandler;

			public void OnPointerDown(PointerEventData eventData)
			{
				Forward(eventData);
			}

			public void OnDrag(PointerEventData eventData)
			{
				Forward(eventData);
			}

			public void OnPointerUp(PointerEventData eventData)
			{
				EndHandler?.Invoke();
			}

			public void OnEndDrag(PointerEventData eventData)
			{
				EndHandler?.Invoke();
			}

			private void Forward(PointerEventData eventData)
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				Transform transform = ((Component)this).transform;
				RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				Vector2 arg = default(Vector2);
				if ((Object)(object)val != (Object)null && RectTransformUtility.ScreenPointToLocalPointInRectangle(val, eventData.position, eventData.pressEventCamera, ref arg))
				{
					Handler?.Invoke(arg, val);
				}
			}
		}

		private sealed class ToggleButton : MonoBehaviour
		{
			private Button _button;

			private TMP_Text _label;

			private Image _background;

			internal event Action Clicked;

			internal void Initialize(Button button, TMP_Text label, Image background)
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				_button = button;
				_label = label;
				_background = background;
				((UnityEvent)_button.onClick).AddListener((UnityAction)delegate
				{
					this.Clicked?.Invoke();
				});
			}

			internal void SetLabel(string label)
			{
				_label.text = label;
			}

			internal void SetState(bool enabled)
			{
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				((Graphic)_background).color = (enabled ? new Color(0.24f, 0.41f, 0.29f, 1f) : new Color(0.18f, 0.23f, 0.3f, 1f));
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__Hide;
		}

		private static readonly Color32[] PresetColors = (Color32[])(object)new Color32[6]
		{
			new Color32(byte.MaxValue, (byte)224, (byte)189, byte.MaxValue),
			new Color32((byte)241, (byte)194, (byte)125, byte.MaxValue),
			new Color32((byte)224, (byte)172, (byte)105, byte.MaxValue),
			new Color32((byte)198, (byte)134, (byte)66, byte.MaxValue),
			new Color32((byte)141, (byte)85, (byte)36, byte.MaxValue),
			new Color32((byte)92, (byte)51, (byte)23, byte.MaxValue)
		};

		private const float ExpandedWidth = 500f;

		private const float ExpandedHeight = 470f;

		private const float MinimizedWidth = 150f;

		private const float MinimizedHeight = 44f;

		private PlayerCustomizationMenu _menu;

		private RectTransform _rootRect;

		private Image _backgroundImage;

		private GameObject _expandedContent;

		private GameObject _minimizedLauncher;

		private Image _launcherSwatch;

		private ToggleButton _toggleButton;

		private ToggleButton _minimizeButton;

		private Image _previewSwatch;

		private TMP_Text _hexLabel;

		private GameObject _advancedArea;

		private RectTransform _wheelHandle;

		private RectTransform _svHandle;

		private Texture2D _wheelTexture;

		private Texture2D _svTexture;

		private float _hue;

		private float _saturation;

		private float _value;

		private float _lastRegenHue = float.NaN;

		private Color32[] _svPixels;

		private bool _dragFinalizing;

		internal void Initialize(PlayerCustomizationMenu menu)
		{
			_menu = menu;
			BuildUi();
			LoadFromState();
			RefreshUi();
			SkinToneState.ApplyToPreview(_menu);
		}

		private void OnDestroy()
		{
			if ((Object)(object)_wheelTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_wheelTexture);
			}
			if ((Object)(object)_svTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_svTexture);
			}
		}

		private void BuildUi()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00ee: 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)
			//IL_0127: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
			_rootRect = ((Component)this).gameObject.GetComponent<RectTransform>();
			if ((Object)(object)_rootRect == (Object)null)
			{
				_rootRect = ((Component)this).gameObject.AddComponent<RectTransform>();
			}
			_rootRect.anchorMin = new Vector2(0f, 0f);
			_rootRect.anchorMax = new Vector2(0f, 0f);
			_rootRect.pivot = new Vector2(0f, 0f);
			_rootRect.sizeDelta = new Vector2(500f, 470f);
			_rootRect.anchoredPosition = new Vector2(12f, 12f);
			_backgroundImage = ((Component)this).gameObject.AddComponent<Image>();
			((Graphic)_backgroundImage).color = new Color(0.08f, 0.1f, 0.14f, 0.94f);
			((Graphic)_backgroundImage).raycastTarget = true;
			_expandedContent = new GameObject("ExpandedContent", new Type[1] { typeof(RectTransform) });
			_expandedContent.transform.SetParent(((Component)this).transform, false);
			RectTransform component = _expandedContent.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			BuildExpandedChrome(component);
			BuildMinimizedLauncher();
		}

		private void BuildExpandedChrome(RectTransform parent)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Expected O, but got Unknown
			float num = 468f;
			float num2 = 12f;
			_minimizeButton = CreateToggleButton(parent, 32f, 32f);
			SetAnchoredTopRow(((Component)_minimizeButton).GetComponent<RectTransform>(), 452f, 12f, 32f, 32f);
			_minimizeButton.SetLabel("–");
			_minimizeButton.Clicked += OnMinimizeClicked;
			TMP_Text obj = CreateLabelUnder(parent, Compatibility.IsMoreSkinColorsPresent ? "Custom Tone Override" : "Custom Tone");
			SetAnchoredTopRow(obj.rectTransform, 16f, num2, num - 40f, 34f);
			obj.fontSize = 28f;
			((Graphic)obj).color = Color.white;
			num2 += 42f;
			RectTransform parent2 = CreateHRowUnder(parent, "Toolbar", 16f, num2, num, 42f);
			_toggleButton = CreateToggleButton(parent2, 160f, 38f);
			_toggleButton.Clicked += OnToggleClicked;
			_previewSwatch = CreateSwatch(parent2, 38f);
			_hexLabel = CreateToolbarLabel(parent2, 160f, 38f);
			num2 += 50f;
			RectTransform parent3 = CreateHRowUnder(parent, "Actions", 16f, num2, num, 38f);
			CreateActionButton(parent3, "Hex", 88f, 34f, OpenHexEditor);
			CreateActionButton(parent3, "Vanilla", 104f, 34f, ResetToVanilla);
			CreateActionButton(parent3, "Default", 104f, 34f, ResetToDefaultPreset);
			num2 += 46f;
			RectTransform parent4 = CreateHRowUnder(parent, "Presets", 16f, num2, num, 34f);
			for (int i = 0; i < PresetColors.Length; i++)
			{
				int presetIndex = i;
				CreatePresetButton(parent4, Color32.op_Implicit(PresetColors[i]), 46f, 30f, delegate
				{
					ApplyPreset(presetIndex);
				});
			}
			num2 += 42f;
			_advancedArea = new GameObject("AdvancedArea", new Type[1] { typeof(RectTransform) });
			_advancedArea.transform.SetParent((Transform)(object)parent, false);
			RectTransform component = _advancedArea.GetComponent<RectTransform>();
			SetAnchoredTopRow(component, 16f, num2, num, 190f);
			float num3 = (num - 380f) * 0.5f;
			Image image;
			RectTransform val = CreateBoxAt(component, "WheelBox", Mathf.Max(0f, num3), 0f, 190f, out image);
			((Graphic)image).color = new Color(0f, 0f, 0f, 0.18f);
			RawImage obj2 = CreateRawImage(val, "WheelImage");
			_wheelTexture = GenerateHueWheelTexture(256, 0.3f, 0.48f);
			obj2.texture = (Texture)(object)_wheelTexture;
			_wheelHandle = CreateHandle(val, 16f);
			AddDragSurface(((Component)val).gameObject, OnWheelPointer);
			Image image2;
			RectTransform val2 = CreateBoxAt(component, "SvBox", Mathf.Max(0f, num3) + 190f + 10f, 0f, 190f, out image2);
			((Graphic)image2).color = new Color(0f, 0f, 0f, 0.18f);
			RawImage obj3 = CreateRawImage(val2, "SvImage");
			_svTexture = new Texture2D(256, 256, (TextureFormat)4, false);
			((Texture)_svTexture).wrapMode = (TextureWrapMode)1;
			((Texture)_svTexture).filterMode = (FilterMode)1;
			obj3.texture = (Texture)(object)_svTexture;
			_svHandle = CreateHandle(val2, 14f);
			AddDragSurface(((Component)val2).gameObject, OnSvPointer);
		}

		private static void SetAnchoredTopRow(RectTransform rect, float x, float y, float width, float height)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(0f, 1f);
			rect.anchorMax = new Vector2(0f, 1f);
			rect.pivot = new Vector2(0f, 1f);
			rect.sizeDelta = new Vector2(width, height);
			rect.anchoredPosition = new Vector2(x, 0f - y);
		}

		private RectTransform CreateHRowUnder(RectTransform parent, string name, float x, float y, float width, float height)
		{
			//IL_0014: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			SetAnchoredTopRow(component, x, y, width, height);
			HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 10f;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			return component;
		}

		private void BuildMinimizedLauncher()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			_minimizedLauncher = new GameObject("MinimizedLauncher", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			_minimizedLauncher.transform.SetParent(((Component)this).transform, false);
			RectTransform component = _minimizedLauncher.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 0f);
			component.anchorMax = new Vector2(0f, 0f);
			component.pivot = new Vector2(0f, 0f);
			component.sizeDelta = new Vector2(150f, 44f);
			component.anchoredPosition = Vector2.zero;
			Image component2 = _minimizedLauncher.GetComponent<Image>();
			((Graphic)component2).color = new Color(0.08f, 0.1f, 0.14f, 0.94f);
			((Graphic)component2).raycastTarget = true;
			((UnityEvent)_minimizedLauncher.GetComponent<Button>().onClick).AddListener(new UnityAction(OnLauncherClicked));
			GameObject val = new GameObject("LauncherSwatch", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(_minimizedLauncher.transform, false);
			SetAnchoredTopRow(val.GetComponent<RectTransform>(), 8f, 8f, 28f, 28f);
			_launcherSwatch = val.GetComponent<Image>();
			((Graphic)_launcherSwatch).raycastTarget = false;
			GameObject val2 = new GameObject("LauncherLabel", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val2.transform.SetParent(_minimizedLauncher.transform, false);
			SetAnchoredTopRow(val2.GetComponent<RectTransform>(), 44f, 8f, 98f, 28f);
			TextMeshProUGUI component3 = val2.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component3).text = "Custom Tone";
			((TMP_Text)component3).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)component3).fontSize = 18f;
			((Graphic)component3).color = Color.white;
			((Graphic)component3).raycastTarget = false;
		}

		private TMP_Text CreateLabelUnder(RectTransform parent, string text)
		{
			TMP_Text obj = Object.Instantiate<TMP_Text>(_menu.unlocked, (Transform)(object)parent);
			obj.text = text;
			((Component)obj).gameObject.SetActive(true);
			obj.alignment = (TextAlignmentOptions)513;
			return obj;
		}

		private RectTransform CreateBoxAt(RectTransform parent, string name, float x, float y, float size, out Image image)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			SetAnchoredTopRow(component, x, y, size, size);
			image = val.GetComponent<Image>();
			((Graphic)image).raycastTarget = true;
			return component;
		}

		private void LoadFromState()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Color.RGBToHSV(SkinToneState.LocalSelection.BaseColor, ref _hue, ref _saturation, ref _value);
			if (_value <= 0.01f)
			{
				_value = 0.01f;
			}
		}

		private void RefreshUi()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			LoadFromState();
			SkinToneSelection skinToneSelection = CurrentSelection();
			bool isPanelMinimized = SkinToneState.IsPanelMinimized;
			if ((Object)(object)_rootRect != (Object)null)
			{
				_rootRect.sizeDelta = (isPanelMinimized ? new Vector2(150f, 44f) : new Vector2(500f, 470f));
			}
			if ((Object)(object)_backgroundImage != (Object)null)
			{
				((Behaviour)_backgroundImage).enabled = !isPanelMinimized;
			}
			if ((Object)(object)_expandedContent != (Object)null)
			{
				_expandedContent.SetActive(!isPanelMinimized);
			}
			if ((Object)(object)_minimizedLauncher != (Object)null)
			{
				_minimizedLauncher.SetActive(isPanelMinimized);
			}
			if ((Object)(object)_launcherSwatch != (Object)null)
			{
				((Graphic)_launcherSwatch).color = skinToneSelection.BaseColor;
			}
			if (isPanelMinimized)
			{
				SkinToneState.ApplyToPreview(_menu);
				return;
			}
			_toggleButton.SetLabel(skinToneSelection.Enabled ? "Custom Tone: On" : "Custom Tone: Off");
			_toggleButton.SetState(skinToneSelection.Enabled);
			if ((Object)(object)_advancedArea != (Object)null)
			{
				_advancedArea.SetActive(true);
			}
			((Graphic)_previewSwatch).color = skinToneSelection.BaseColor;
			_hexLabel.text = $"{SkinToneSelection.ToHtml(skinToneSelection.BaseColor)}  Loadout {SkinToneState.ActiveLoadoutIndex + 1}";
			RegenerateSvTexture();
			UpdateHandles();
		}

		private void OnMinimizeClicked()
		{
			SkinToneState.IsPanelMinimized = true;
			RefreshUi();
		}

		private void OnLauncherClicked()
		{
			SkinToneState.IsPanelMinimized = false;
			RefreshUi();
		}

		private SkinToneSelection CurrentSelection()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			SkinToneSelection result = default(SkinToneSelection);
			result.Enabled = SkinToneState.LocalSelection.Enabled;
			result.BaseColor = Color.HSVToRGB(_hue, _saturation, _value);
			return result;
		}

		private void OnToggleClicked()
		{
			SkinToneSelection selection = CurrentSelection();
			selection.Enabled = !SkinToneState.LocalSelection.Enabled;
			SkinToneState.SetLocalSelection(selection, persist: true, broadcast: true);
			RefreshUi();
		}

		private void ApplyPreset(int presetIndex)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Color.RGBToHSV(Color32.op_Implicit(PresetColors[presetIndex]), ref _hue, ref _saturation, ref _value);
			SkinToneSelection selection = CurrentSelection();
			selection.Enabled = true;
			SkinToneState.SetLocalSelection(selection, persist: true, broadcast: true);
			RefreshUi();
		}

		private void ResetToVanilla()
		{
			SkinToneSelection localSelection = SkinToneState.LocalSelection;
			localSelection.Enabled = false;
			SkinToneState.SetLocalSelection(localSelection, persist: true, broadcast: true);
			RefreshUi();
		}

		private void ResetToDefaultPreset()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Color.RGBToHSV(Color32.op_Implicit(SkinToneSelection.DefaultBaseColor), ref _hue, ref _saturation, ref _value);
			SkinToneSelection selection = CurrentSelection();
			selection.Enabled = true;
			SkinToneState.SetLocalSelection(selection, persist: true, broadcast: true);
			RefreshUi();
		}

		private void OpenHexEditor()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			string text = SkinToneSelection.ToHtml(CurrentSelection().BaseColor);
			ButtonEntry[] obj = new ButtonEntry[2]
			{
				new ButtonEntry("Apply", new UnityAction(ApplyHexFromDialog), false, true),
				default(ButtonEntry)
			};
			object obj2 = <>O.<0>__Hide;
			if (obj2 == null)
			{
				UnityAction val = FullScreenMessage.Hide;
				<>O.<0>__Hide = val;
				obj2 = (object)val;
			}
			obj[1] = new ButtonEntry("Cancel", (UnityAction)obj2, true, false);
			FullScreenMessage.ShowTextField("Enter a skin tone hex value like #D8A074.", "Hex color", text, "Custom Skin Tone", false, 7, (ButtonEntry[])(object)obj);
		}

		private void ApplyHexFromDialog()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (TryParseHex(FullScreenMessage.InputFieldText, out var color))
			{
				Color.RGBToHSV(color, ref _hue, ref _saturation, ref _value);
				SkinToneSelection selection = CurrentSelection();
				selection.Enabled = true;
				SkinToneState.SetLocalSelection(selection, persist: true, broadcast: true);
				FullScreenMessage.Hide();
				RefreshUi();
			}
			else
			{
				FullScreenMessage.ShowErrorMessage("Please enter a valid #RRGGBB color.", "", "", int.MaxValue, false);
			}
		}

		private void OnWheelPointer(Vector2 localPoint, RectTransform rect)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Rect rect2 = rect.rect;
			Vector2 val = localPoint - ((Rect)(ref rect2)).center;
			float x = val.x;
			rect2 = rect.rect;
			float num = x / (((Rect)(ref rect2)).width * 0.5f);
			float y = val.y;
			rect2 = rect.rect;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(num, y / (((Rect)(ref rect2)).height * 0.5f));
			float magnitude = ((Vector2)(ref val2)).magnitude;
			if (!(magnitude < 0.3f) && !(magnitude > 0.48f))
			{
				_hue = Mathf.Repeat(Mathf.Atan2(val2.y, val2.x) / ((float)Math.PI * 2f), 1f);
				CommitSelectionLive();
			}
		}

		private void OnSvPointer(Vector2 localPoint, RectTransform rect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			Rect rect2 = rect.rect;
			float xMin = ((Rect)(ref rect2)).xMin;
			rect2 = rect.rect;
			float num = Mathf.InverseLerp(xMin, ((Rect)(ref rect2)).xMax, localPoint.x);
			rect2 = rect.rect;
			float yMin = ((Rect)(ref rect2)).yMin;
			rect2 = rect.rect;
			float num2 = Mathf.InverseLerp(yMin, ((Rect)(ref rect2)).yMax, localPoint.y);
			_saturation = Mathf.Clamp01(num);
			_value = Mathf.Clamp01(num2);
			CommitSelectionLive();
		}

		private void CommitSelectionLive()
		{
			SkinToneSelection selection = CurrentSelection();
			if (!SkinToneState.LocalSelection.Enabled)
			{
				selection.Enabled = false;
			}
			SkinToneState.SetLocalSelection(selection, persist: false, broadcast: false);
			RefreshUi();
		}

		private void OnDragFinished()
		{
			if (_dragFinalizing)
			{
				return;
			}
			_dragFinalizing = true;
			try
			{
				SkinToneSelection selection = CurrentSelection();
				if (!SkinToneState.LocalSelection.Enabled)
				{
					selection.Enabled = false;
				}
				SkinToneState.SetLocalSelection(selection, persist: true, broadcast: true);
			}
			finally
			{
				_dragFinalizing = false;
			}
		}

		private void RegenerateSvTexture()
		{
			//IL_008a: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if (!float.IsNaN(_lastRegenHue) && Mathf.Abs(_hue - _lastRegenHue) < 0.003f)
			{
				return;
			}
			int width = ((Texture)_svTexture).width;
			int height = ((Texture)_svTexture).height;
			if (_svPixels == null || _svPixels.Length != width * height)
			{
				_svPixels = (Color32[])(object)new Color32[width * height];
			}
			int num = 0;
			for (int i = 0; i < height; i++)
			{
				float num2 = (float)i / (float)(height - 1);
				for (int j = 0; j < width; j++)
				{
					float num3 = (float)j / (float)(width - 1);
					Color val = Color.HSVToRGB(_hue, num3, num2);
					_svPixels[num++] = new Color32((byte)(val.r * 255f), (byte)(val.g * 255f), (byte)(val.b * 255f), byte.MaxValue);
				}
			}
			_svTexture.SetPixels32(_svPixels);
			_svTexture.Apply(false, false);
			_lastRegenHue = _hue;
		}

		private void UpdateHandles()
		{
			//IL_001c: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)_wheelHandle).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			float num;
			if (val == null)
			{
				num = 95f;
			}
			else
			{
				Rect rect = val.rect;
				num = ((Rect)(ref rect)).width * 0.5f;
			}
			float num2 = num * 0.78f;
			float num3 = num - 4f;
			float num4 = _hue * (float)Math.PI * 2f;
			_wheelHandle.anchoredPosition = new Vector2(Mathf.Cos(num4), Mathf.Sin(num4)) * num2;
			_svHandle.anchoredPosition = new Vector2(Mathf.Lerp(0f - num3, num3, _saturation), Mathf.Lerp(0f - num3, num3, _value));
		}

		private TMP_Text CreateLabel(string text)
		{
			TMP_Text obj = Object.Instantiate<TMP_Text>(_menu.unlocked, ((Component)this).transform);
			obj.text = text;
			((Component)obj).gameObject.SetActive(true);
			obj.alignment = (TextAlignmentOptions)513;
			return obj;
		}

		private TMP_Text CreateToolbarLabel(RectTransform parent, float width, float height)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text obj = CreateLabel(string.Empty);
			obj.transform.SetParent((Transform)(object)parent, false);
			obj.fontSize = 18f;
			((Graphic)obj).color = Color.white;
			obj.alignment = (TextAlignmentOptions)513;
			RectTransform rectTransform = obj.rectTransform;
			rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			rectTransform.pivot = new Vector2(0.5f, 0.5f);
			rectTransform.sizeDelta = new Vector2(width, height);
			return obj;
		}

		private RawImage CreateRawImage(RectTransform parent, string name)
		{
			//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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(RawImage)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = new Vector2(8f, 8f);
			component.offsetMax = new Vector2(-8f, -8f);
			return val.GetComponent<RawImage>();
		}

		private RectTransform CreateHandle(RectTransform parent, float size)
		{
			//IL_0025: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Handle", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = Color.white;
			((Graphic)component).raycastTarget = false;
			RectTransform component2 = val.GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0.5f, 0.5f);
			component2.anchorMax = new Vector2(0.5f, 0.5f);
			component2.sizeDelta = new Vector2(size, size);
			return component2;
		}

		private Image CreateSwatch(RectTransform parent, float size)
		{
			//IL_0025: 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_0037: 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)
			GameObject val = new GameObject("PreviewSwatch", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(size, size);
			return val.GetComponent<Image>();
		}

		private void AddDragSurface(GameObject target, Action<Vector2, RectTransform> callback)
		{
			ColorDragSurface colorDragSurface = target.AddComponent<ColorDragSurface>();
			colorDragSurface.Handler = callback;
			colorDragSurface.EndHandler = OnDragFinished;
		}

		private ToggleButton CreateToggleButton(RectTransform parent, float width, float height)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_004d: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ToggleButton", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(0.18f, 0.23f, 0.3f, 1f);
			ToggleButton toggleButton = val.AddComponent<ToggleButton>();
			GameObject val2 = new GameObject("Label", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform component2 = val2.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = new Vector2(10f, 6f);
			component2.offsetMax = new Vector2(-10f, -6f);
			TextMeshProUGUI component3 = val2.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component3).alignment = (TextAlignmentOptions)514;
			((TMP_Text)component3).fontSize = 20f;
			((Graphic)component3).color = Color.white;
			toggleButton.Initialize(val.GetComponent<Button>(), (TMP_Text)(object)component3, component);
			return toggleButton;
		}

		private void CreateActionButton(RectTransform parent, string label, float width, float height, Action onClick)
		{
			ToggleButton toggleButton = CreateToggleButton(parent, width, height);
			toggleButton.SetLabel(label);
			toggleButton.Clicked += onClick;
		}

		private void CreatePresetButton(RectTransform parent, Color color, float width, float height, Action onClick)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			GameObject val = new GameObject("PresetButton", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent((Transform)(object)parent, false);
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
			((Graphic)val.GetComponent<Image>()).color = color;
			((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				onClick();
			});
		}

		private Texture2D GenerateHueWheelTexture(int size, float innerRadius, float outerRadius)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			float num = (float)(size - 1) * 0.5f;
			Vector2 val2 = default(Vector2);
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					((Vector2)(ref val2))..ctor(((float)j - num) / num, ((float)i - num) / num);
					float magnitude = ((Vector2)(ref val2)).magnitude;
					if (magnitude < innerRadius || magnitude > outerRadius)
					{
						val.SetPixel(j, i, Color.clear);
						continue;
					}
					Color val3 = Color.HSVToRGB(Mathf.Repeat(Mathf.Atan2(val2.y, val2.x) / ((float)Math.PI * 2f), 1f), 1f, 1f);
					val3.a = 1f;
					val.SetPixel(j, i, val3);
				}
			}
			val.Apply(false, false);
			return val;
		}

		private static bool TryParseHex(string input, out Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			if (string.IsNullOrWhiteSpace(input))
			{
				return false;
			}
			string text = input.Trim();
			if (!text.StartsWith("#", StringComparison.Ordinal))
			{
				text = "#" + text;
			}
			if (!ColorUtility.TryParseHtmlString(text, ref color))
			{
				return false;
			}
			color.a = 1f;
			return true;
		}
	}
	internal struct SkinToneSelection : IEquatable<SkinToneSelection>
	{
		internal static readonly Color32 DefaultBaseColor = new Color32((byte)216, (byte)160, (byte)116, byte.MaxValue);

		public bool Enabled;

		public Color BaseColor;

		public Color MouthColor
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				float num = default(float);
				float num2 = default(float);
				float num3 = default(float);
				Color.RGBToHSV(BaseColor, ref num, ref num2, ref num3);
				return Color.HSVToRGB(num, Mathf.Clamp01(num2 * 0.7f), Mathf.Clamp(num3 * 0.48f, 0.06f, 0.95f));
			}
		}

		public bool Equals(SkinToneSelection other)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled == other.Enabled)
			{
				return ((Color)(ref BaseColor)).Equals(other.BaseColor);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is SkinToneSelection other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return ((Enabled ? 1 : 0) * 397) ^ ((object)(Color)(ref BaseColor)).GetHashCode();
		}

		public static string ToHtml(Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return "#" + ColorUtility.ToHtmlStringRGB(color);
		}
	}
	internal static class SkinToneState
	{
		private const int LoadoutCount = 4;

		private static readonly Dictionary<uint, SkinToneSelection> RemoteSelections = new Dictionary<uint, SkinToneSelection>();

		private static ManualLogSource _log;

		private static readonly ConfigEntry<bool>[] EnabledConfigs = new ConfigEntry<bool>[4];

		private static readonly ConfigEntry<string>[] BaseColorConfigs = new ConfigEntry<string>[4];

		private static readonly SkinToneSelection[] LocalSelectionsByLoadout = new SkinToneSelection[4];

		private static SkinToneSelection _localSelection;

		private static int _activeLoadoutIndex;

		private static ConfigEntry<bool> _panelMinimizedConfig;

		[ThreadStatic]
		private static bool _isRevertingToVanilla;

		internal static SkinToneSelection LocalSelection => _localSelection;

		internal static int ActiveLoadoutIndex => _activeLoadoutIndex;

		internal static bool IsRevertingToVanilla => _isRevertingToVanilla;

		internal static bool IsPanelMinimized
		{
			get
			{
				if (_panelMinimizedConfig != null)
				{
					return _panelMinimizedConfig.Value;
				}
				return false;
			}
			set
			{
				if (_panelMinimizedConfig != null && _panelMinimizedConfig.Value != value)
				{
					_panelMinimizedConfig.Value = value;
					((ConfigEntryBase)_panelMinimizedConfig).ConfigFile.Save();
				}
			}
		}

		internal static void Initialize(ConfigFile config, ManualLogSource log)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			_log = log;
			for (int i = 0; i < 4; i++)
			{
				EnabledConfigs[i] = config.Bind<bool>($"CustomSkinTone.Loadout{i}", "Enabled", true, $"Whether the custom skin tone override is enabled for loadout {i + 1}.");
				BaseColorConfigs[i] = config.Bind<string>($"CustomSkinTone.Loadout{i}", "BaseColor", SkinToneSelection.ToHtml(Color32.op_Implicit(SkinToneSelection.DefaultBaseColor)), $"Custom skin tone hex color for loadout {i + 1} (#RRGGBB).");
				LocalSelectionsByLoadout[i] = new SkinToneSelection
				{
					Enabled = EnabledConfigs[i].Value,
					BaseColor = ParseColor(BaseColorConfigs[i].Value, Color32.op_Implicit(SkinToneSelection.DefaultBaseColor))
				};
			}
			_activeLoadoutIndex = 0;
			_localSelection = LocalSelectionsByLoadout[_activeLoadoutIndex];
			SkinToneDebugState.RecordLoadoutActivated(_activeLoadoutIndex, _localSelection);
			_panelMinimizedConfig = config.Bind<bool>("Picker.Panel", "Minimized", false, "Whether the custom skin tone picker panel starts minimized to a small launcher button. Toggle in the menu via the – / ⤢ button.");
		}

		internal static void SetLocalSelection(SkinToneSelection selection, bool persist, bool broadcast)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			_localSelection = selection;
			LocalSelectionsByLoadout[_activeLoadoutIndex] = selection;
			SkinToneDebugState.RecordSelectionChanged(_activeLoadoutIndex, selection);
			if (persist)
			{
				EnabledConfigs[_activeLoadoutIndex].Value = selection.Enabled;
				BaseColorConfigs[_activeLoadoutIndex].Value = SkinToneSelection.ToHtml(selection.BaseColor);
				((ConfigEntryBase)EnabledConfigs[_activeLoadoutIndex]).ConfigFile.Save();
			}
			ApplyToPreview(SingletonBehaviour<PlayerCustomizationMenu>.Instance);
			if (broadcast)
			{
				SkinToneNetwork.TryBroadcastLocalSelection(selection);
			}
		}

		internal static void ActivateLoadout(int index, bool applyPreview, bool broadcast)
		{
			_activeLoadoutIndex = NormalizeLoadoutIndex(index);
			_localSelection = LocalSelectionsByLoadout[_activeLoadoutIndex];
			SkinToneDebugState.RecordLoadoutActivated(_activeLoadoutIndex, _localSelection);
			if (applyPreview)
			{
				ApplyToPreview(SingletonBehaviour<PlayerCustomizationMenu>.Instance);
			}
			if (broadcast)
			{
				SkinToneNetwork.TryBroadcastLocalSelection(_localSelection);
			}
		}

		internal static void ApplyToPreview(PlayerCustomizationMenu menu)
		{
			if (!((Object)(object)menu == (Object)null) && !((Object)(object)menu.characterPreview == (Object)null) && !((Object)(object)menu.characterPreview.cosmeticsSwitcher == (Object)null))
			{
				if (_localSelection.Enabled)
				{
					SkinToneDebugState.RecordApplyPreview(_localSelection);
					SkinToneMaterialApplier.Apply(menu.characterPreview.cosmeticsSwitcher, _localSelection);
				}
				else
				{
					SkinToneDebugState.RecordRevert(0u, isPreview: true);
					RevertToVanilla(menu.characterPreview.cosmeticsSwitcher);
				}
			}
		}

		internal static void SetRemoteSelection(uint netId, SkinToneSelection selection)
		{
			RemoteSelections[netId] = selection;
			TryApplyToSpawnedPlayer(netId);
		}

		internal static void ClearRemoteSelection(uint netId)
		{
			RemoteSelections.Remove(netId);
			TryApplyToSpawnedPlayer(netId);
		}

		internal static bool TryGetRemoteSelection(uint netId, out SkinToneSelection selection)
		{
			return RemoteSelections.TryGetValue(netId, out selection);
		}

		internal static void TryApplyToSpawnedPlayer(uint netId)
		{
			if (!NetworkClient.spawned.TryGetValue(netId, out var value) || (Object)(object)value == (Object)null)
			{
				return;
			}
			PlayerCosmetics val = ((Component)value).GetComponent<PlayerCosmetics>();
			if ((Object)(object)val == (Object)null)
			{
				PlayerInfo component = ((Component)value).GetComponent<PlayerInfo>();
				val = (((Object)(object)component != (Object)null) ? component.Cosmetics : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			PlayerCosmeticsSwitcher component2 = ((Component)val).GetComponent<PlayerCosmeticsSwitcher>();
			if (!((Object)(object)component2 == (Object)null))
			{
				if (RemoteSelections.TryGetValue(netId, out var value2) && value2.Enabled)
				{
					SkinToneDebugState.RecordApplyPlayer(netId, value2);
					SkinToneMaterialApplier.Apply(component2, value2);
				}
				else
				{
					SkinToneDebugState.RecordRevert(netId, isPreview: false);
					RevertToVanilla(component2);
				}
			}
		}

		internal static void TryApplyFor(PlayerCosmetics cosmetics)
		{
			if ((Object)(object)cosmetics == (Object)null)
			{
				return;
			}
			PlayerCosmeticsSwitcher component = ((Component)cosmetics).GetComponent<PlayerCosmeticsSwitcher>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			SkinToneSelection value;
			if (((NetworkBehaviour)cosmetics).isLocalPlayer)
			{
				if (_localSelection.Enabled)
				{
					SkinToneDebugState.RecordApplyPlayer(((NetworkBehaviour)cosmetics).netId, _localSelection);
					SkinToneMaterialApplier.Apply(component, _localSelection);
				}
				else
				{
					SkinToneDebugState.RecordRevert(((NetworkBehaviour)cosmetics).netId, isPreview: false);
					RevertToVanilla(component);
				}
			}
			else if (RemoteSelections.TryGetValue(((NetworkBehaviour)cosmetics).netId, out value) && value.Enabled)
			{
				SkinToneDebugState.RecordApplyPlayer(((NetworkBehaviour)cosmetics).netId, value);
				SkinToneMaterialApplier.Apply(component, value);
			}
		}

		internal static void OnLocalPlayerStarted(PlayerCosmetics cosmetics)
		{
			ActivateLoadout(cosmetics.GetEquippedLoadoutIndex(), applyPreview: true, broadcast: false);
			TryApplyFor(cosmetics);
			SkinToneNetwork.TryBroadcastLocalSelection(_localSelection);
		}

		private static Color ParseColor(string raw, Color fallback)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			if (!string.IsNullOrWhiteSpace(raw) && ColorUtility.TryParseHtmlString(raw, ref result))
			{
				result.a = 1f;
				return result;
			}
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogWarning((object)("Invalid custom skin tone '" + raw + "', using fallback."));
			}
			fallback.a = 1f;
			return fallback;
		}

		internal static void RevertToVanilla(PlayerCosmeticsSwitcher switcher)
		{
			if ((Object)(object)switcher == (Object)null)
			{
				return;
			}
			bool isRevertingToVanilla = _isRevertingToVanilla;
			_isRevertingToVanilla = true;
			try
			{
				switcher.SetSkinColor(switcher.CurrentSkinColorIndex);
			}
			finally
			{
				_isRevertingToVanilla = isRevertingToVanilla;
			}
		}

		private static int NormalizeLoadoutIndex(int index)
		{
			return Mathf.Clamp(index, 0, 3);
		}
	}
}