Decompiled source of ReLoupKing v1.0.1

plugins/ReLoupKing/ReLoupKing.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using Fusion;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ReLoupKing.Patches;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ReLoupKing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+df7be29cd7f81e31918698ada9a23b5783ec31b9")]
[assembly: AssemblyProduct("ReLoupKing")]
[assembly: AssemblyTitle("ReLoupKing")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ReLoupKing
{
	public enum CustomizerElement
	{
		Hair
	}
	public struct HairColorInfo
	{
		public string Name;

		public Color32 TargetColor;

		public HairColorInfo(string name, byte r, byte g, byte b)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			TargetColor = new Color32(r, g, b, byte.MaxValue);
		}
	}
	public struct PlayerHairState
	{
		public int PresetIndex;

		public string CustomHex;

		public Color32 Color;

		public bool IsCustom => !string.IsNullOrEmpty(CustomHex);

		public PlayerHairState(int presetIndex, string customHex, Color32 color)
		{
			//IL_000f: 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)
			PresetIndex = presetIndex;
			CustomHex = customHex;
			Color = color;
		}
	}
	public static class AppearanceManager
	{
		public const string PREFS_HAIR_KEY = "CUSTOM_HAIR_COLOR_INDEX";

		public const string PREFS_HAIR_HEX_KEY = "CUSTOM_HAIR_COLOR_HEX";

		public static readonly HairColorInfo[] HairColors = new HairColorInfo[20]
		{
			new HairColorInfo("color1", 90, 68, 40),
			new HairColorInfo("color2", 240, 210, 110),
			new HairColorInfo("color3", 40, 40, 45),
			new HairColorInfo("color4", 210, 85, 30),
			new HairColorInfo("color5", 225, 225, 235),
			new HairColorInfo("color6", 210, 35, 45),
			new HairColorInfo("color7", 45, 95, 225),
			new HairColorInfo("color8", 40, 195, 80),
			new HairColorInfo("color9", 245, 95, 175),
			new HairColorInfo("color10", 165, 55, 225),
			new HairColorInfo("color11", 45, 225, 225),
			new HairColorInfo("color12", 245, 135, 35),
			new HairColorInfo("color13", 60, 42, 30),
			new HairColorInfo("color14", 140, 75, 40),
			new HairColorInfo("color15", 205, 190, 160),
			new HairColorInfo("color16", 235, 150, 115),
			new HairColorInfo("color17", 120, 25, 50),
			new HairColorInfo("color18", 195, 160, 230),
			new HairColorInfo("color19", 110, 225, 170),
			new HairColorInfo("color20", 115, 120, 130)
		};

		public const int MaxCachedTextures = 32;

		private static readonly Dictionary<string, Texture2D> TextureCache = new Dictionary<string, Texture2D>();

		private static readonly LinkedList<string> TextureCacheLru = new LinkedList<string>();

		private static readonly Dictionary<PlayerRef, PlayerHairState> PlayerHairStates = new Dictionary<PlayerRef, PlayerHairState>();

		private static readonly Regex AppearanceTagRegex = new Regex("#[a-zA-Z_]+=[a-zA-Z0-9#]+(\\.[a-zA-Z0-9]+)?", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private static bool _lycansReflectionInitialized = false;

		private static MethodInfo _getPlayerOutfitIndexMethod = null;

		private static FieldInfo _playerOutfitIndexField = null;

		private static readonly Dictionary<PlayerRef, Texture> OriginalTextures = new Dictionary<PlayerRef, Texture>();

		private static readonly MethodInfo RpcDefinePlayerDataMethod = AccessTools.Method(typeof(PlayerController), "Rpc_DefinePlayerData", new Type[1] { typeof(NetworkPlayerData) }, (Type[])null);

		public static CustomizerElement CurrentElement { get; set; } = CustomizerElement.Hair;

		public static int GetSavedHair()
		{
			return PlayerPrefs.GetInt("CUSTOM_HAIR_COLOR_INDEX", 0);
		}

		public static void SetSavedHair(int index)
		{
			PlayerPrefs.SetInt("CUSTOM_HAIR_COLOR_INDEX", index);
			PlayerPrefs.SetString("CUSTOM_HAIR_COLOR_HEX", string.Empty);
			PlayerPrefs.Save();
		}

		public static string GetSavedHairHex()
		{
			return PlayerPrefs.GetString("CUSTOM_HAIR_COLOR_HEX", string.Empty);
		}

		public static void SetSavedHairHex(string hex)
		{
			PlayerPrefs.SetString("CUSTOM_HAIR_COLOR_HEX", hex ?? string.Empty);
			PlayerPrefs.Save();
		}

		public static PlayerHairState GetSavedHairState()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			string savedHairHex = GetSavedHairHex();
			if (!string.IsNullOrEmpty(savedHairHex) && TryParseHex(savedHairHex, out var color))
			{
				return new PlayerHairState(-1, savedHairHex.ToUpper(), color);
			}
			int savedHair = GetSavedHair();
			return new PlayerHairState(savedHair, null, GetHairInfo(savedHair).TargetColor);
		}

		public static int GetHairCount()
		{
			return HairColors.Length;
		}

		public static HairColorInfo GetHairInfo(int index)
		{
			if (index >= 0 && index < HairColors.Length)
			{
				return HairColors[index];
			}
			return HairColors[0];
		}

		public static bool TryParseHex(string hexStr, out Color32 color)
		{
			//IL_0001: 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)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color32);
			if (string.IsNullOrEmpty(hexStr))
			{
				return false;
			}
			string text = hexStr.Trim();
			if (text.StartsWith("#"))
			{
				text = text.Substring(1);
			}
			if (text.Length != 6 || !Regex.IsMatch(text, "^[0-9a-fA-F]{6}$"))
			{
				return false;
			}
			try
			{
				byte b = byte.Parse(text.Substring(0, 2), NumberStyles.HexNumber);
				byte b2 = byte.Parse(text.Substring(2, 2), NumberStyles.HexNumber);
				byte b3 = byte.Parse(text.Substring(4, 2), NumberStyles.HexNumber);
				color = new Color32(b, b2, b3, byte.MaxValue);
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static PlayerHairState? ExtractHairState(string id)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(id))
			{
				return null;
			}
			Match match = Regex.Match(id, "#hair=H([0-9a-fA-F]{6})", RegexOptions.IgnoreCase);
			if (match.Success)
			{
				string text = match.Groups[1].Value.ToUpper();
				if (TryParseHex(text, out var color))
				{
					return new PlayerHairState(-1, text, color);
				}
			}
			Match match2 = Regex.Match(id, "#hair=(\\d+)", RegexOptions.IgnoreCase);
			if (match2.Success && int.TryParse(match2.Groups[1].Value, out var result))
			{
				result = Mathf.Clamp(result, 0, HairColors.Length - 1);
				return new PlayerHairState(result, null, GetHairInfo(result).TargetColor);
			}
			return null;
		}

		public static int ExtractHair(string id)
		{
			PlayerHairState? playerHairState = ExtractHairState(id);
			if (!playerHairState.HasValue)
			{
				return -1;
			}
			if (playerHairState.Value.PresetIndex < 0)
			{
				return 0;
			}
			return playerHairState.Value.PresetIndex;
		}

		public static string CleanAppearanceTags(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return string.Empty;
			}
			return AppearanceTagRegex.Replace(id, string.Empty);
		}

		public static string BuildCustomId(string currentId, PlayerHairState hairState)
		{
			string text = CleanAppearanceTags(currentId);
			if (hairState.IsCustom)
			{
				return text + "#hair=H" + hairState.CustomHex.ToUpper();
			}
			if (hairState.PresetIndex > 0)
			{
				return $"{text}#hair={hairState.PresetIndex}";
			}
			return text;
		}

		public static string BuildCustomId(string currentId, int hairIndex)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return BuildCustomId(currentId, new PlayerHairState(hairIndex, null, GetHairInfo(hairIndex).TargetColor));
		}

		public static PlayerHairState GetPlayerHairState(PlayerController player)
		{
			//IL_0015: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_00af: 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)
			if ((Object)(object)player == (Object)null)
			{
				return GetSavedHairState();
			}
			if (PlayerHairStates.TryGetValue(player.Ref, out var value))
			{
				return value;
			}
			PlayerHairState? playerHairState = ExtractHairState(((object)player.PlayerData.ID/*cast due to .constrained prefix*/).ToString());
			if (playerHairState.HasValue)
			{
				PlayerHairStates[player.Ref] = playerHairState.Value;
				return playerHairState.Value;
			}
			if (((SimulationBehaviour)player).HasInputAuthority)
			{
				PlayerHairState savedHairState = GetSavedHairState();
				PlayerHairStates[player.Ref] = savedHairState;
				return savedHairState;
			}
			PlayerHairState playerHairState2 = new PlayerHairState(0, null, HairColors[0].TargetColor);
			PlayerHairStates[player.Ref] = playerHairState2;
			return playerHairState2;
		}

		public static int GetPlayerHair(PlayerController player)
		{
			PlayerHairState playerHairState = GetPlayerHairState(player);
			if (playerHairState.PresetIndex < 0)
			{
				return 0;
			}
			return playerHairState.PresetIndex;
		}

		public static void InvalidatePlayerCache(PlayerRef playerRef)
		{
			//IL_0005: 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)
			PlayerHairStates.Remove(playerRef);
			OriginalTextures.Remove(playerRef);
		}

		public static void ClearAllPlayerCaches()
		{
			PlayerHairStates.Clear();
			OriginalTextures.Clear();
			ClearTextureCache();
		}

		public static void ClearTextureCache()
		{
			foreach (KeyValuePair<string, Texture2D> item in TextureCache)
			{
				if ((Object)(object)item.Value != (Object)null)
				{
					Object.Destroy((Object)(object)item.Value);
				}
			}
			TextureCache.Clear();
			TextureCacheLru.Clear();
		}

		public static int GetLycansNewRolesOutfitIndex(PlayerRef playerRef, int playerIndex)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			if (!_lycansReflectionInitialized)
			{
				_lycansReflectionInitialized = true;
				try
				{
					Type type = AccessTools.TypeByName("LycansNewRoles.Patches.PlayerControllerPatch") ?? AccessTools.TypeByName("LycansNewRoles.PlayerControllerPatch");
					if (type != null)
					{
						_getPlayerOutfitIndexMethod = AccessTools.Method(type, "GetPlayerOutfitIndex", new Type[1] { typeof(PlayerRef) }, (Type[])null);
						_playerOutfitIndexField = AccessTools.Field(type, "playerOutfitIndex") ?? AccessTools.Field(type, "PlayerOutfitIndex");
					}
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogWarning((object)("[AppearanceManager] LycansNewRoles reflection setup note: " + ex.Message));
				}
			}
			if (_getPlayerOutfitIndexMethod != null)
			{
				try
				{
					if (_getPlayerOutfitIndexMethod.Invoke(null, new object[1] { playerRef }) is int result)
					{
						return result;
					}
				}
				catch
				{
				}
			}
			if (_playerOutfitIndexField != null)
			{
				try
				{
					if (_playerOutfitIndexField.GetValue(null) is IDictionary dictionary && dictionary.Contains(playerRef))
					{
						return (int)dictionary[playerRef];
					}
				}
				catch
				{
				}
			}
			return playerIndex;
		}

		public static void ApplyAppearanceToPlayer(PlayerController player, PlayerHairState? overrideState = null, int overrideOutfitIndex = -1, bool updateCache = true)
		{
			//IL_019e: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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)
			if ((Object)(object)player == (Object)null || NetworkBool.op_Implicit(player.IsWolf))
			{
				return;
			}
			try
			{
				SkinnedMeshRenderer val = Traverse.Create((object)player).Field<SkinnedMeshRenderer>("villagerMeshRenderer").Value ?? Traverse.Create((object)player).Field<SkinnedMeshRenderer>("_villagerMeshRenderer").Value;
				if ((Object)(object)val == (Object)null || (Object)(object)((Renderer)val).material == (Object)null)
				{
					return;
				}
				PlayerHairState playerHairState = overrideState ?? GetPlayerHairState(player);
				int num = ((overrideOutfitIndex >= 0) ? overrideOutfitIndex : GetLycansNewRolesOutfitIndex(player.Ref, player.Index));
				Texture value = null;
				try
				{
					value = ColorManager.GetTexture(num);
				}
				catch
				{
				}
				if ((Object)(object)value == (Object)null && (!OriginalTextures.TryGetValue(player.Ref, out value) || (Object)(object)value == (Object)null))
				{
					value = ((Renderer)val).material.mainTexture;
					if ((Object)(object)value != (Object)null)
					{
						OriginalTextures[player.Ref] = value;
					}
				}
				if (!((Object)(object)value == (Object)null))
				{
					Texture tintedTexture = GetTintedTexture(value, num, playerHairState);
					if ((Object)(object)tintedTexture != (Object)null)
					{
						((Renderer)val).material.mainTexture = tintedTexture;
					}
					if (updateCache)
					{
						PlayerHairStates[player.Ref] = playerHairState;
					}
					string arg = (playerHairState.IsCustom ? ("hex #" + playerHairState.CustomHex) : $"color #{playerHairState.PresetIndex}");
					Plugin.Logger.LogInfo((object)$"[ApplyAppearance] Applied hair {arg} to {player.Ref} (outfit {num})");
				}
			}
			catch (Exception arg2)
			{
				Plugin.Logger.LogError((object)$"Error applying appearance to {player.Ref}: {arg2}");
			}
		}

		public static void ApplyAppearanceToPlayer(PlayerController player, int hairIndex, int overrideOutfitIndex = -1, bool updateCache = true)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			PlayerHairState value = new PlayerHairState(hairIndex, null, GetHairInfo(hairIndex).TargetColor);
			ApplyAppearanceToPlayer(player, value, overrideOutfitIndex, updateCache);
		}

		public static Texture GetTintedTexture(Texture baseTexture, int outfitIndex, PlayerHairState hairState)
		{
			//IL_00dc: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)baseTexture == (Object)null)
			{
				return null;
			}
			if (!hairState.IsCustom && hairState.PresetIndex <= 0)
			{
				return baseTexture;
			}
			string text = (hairState.IsCustom ? $"{outfitIndex}_hex_{hairState.CustomHex.ToUpper()}" : $"{outfitIndex}_h{hairState.PresetIndex}");
			if (TextureCache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null)
			{
				TextureCacheLru.Remove(text);
				TextureCacheLru.AddLast(text);
				return (Texture)(object)value;
			}
			Texture2D val = MakeReadable(baseTexture);
			if ((Object)(object)val == (Object)null)
			{
				return baseTexture;
			}
			Color32[] pixels = val.GetPixels32();
			Color32[] basePixels = (Color32[])pixels.Clone();
			int width = ((Texture)val).width;
			int height = ((Texture)val).height;
			float num = (float)width / 2048f;
			float num2 = (float)height / 2048f;
			Color32 color = hairState.Color;
			byte r = color.r;
			byte g = color.g;
			byte b = color.b;
			ApplyHairTintRegion(pixels, basePixels, width, (int)(0f * num), (int)(725f * num), (int)(497f * num2), (int)(1360f * num2), r, g, b);
			val.SetPixels32(pixels);
			val.Apply(false, false);
			((Object)val).name = "Tinted_" + text;
			while (TextureCache.Count >= 32 && TextureCacheLru.Count > 0)
			{
				string value2 = TextureCacheLru.First.Value;
				TextureCacheLru.RemoveFirst();
				if (TextureCache.TryGetValue(value2, out var value3) && (Object)(object)value3 != (Object)null)
				{
					Object.Destroy((Object)(object)value3);
				}
				TextureCache.Remove(value2);
			}
			TextureCache[text] = val;
			TextureCacheLru.AddLast(text);
			return (Texture)(object)val;
		}

		public static Texture GetTintedTexture(Texture baseTexture, int outfitIndex, int hairIndex)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return GetTintedTexture(baseTexture, outfitIndex, new PlayerHairState(hairIndex, null, GetHairInfo(hairIndex).TargetColor));
		}

		private static void ApplyHairTintRegion(Color32[] pixels, Color32[] basePixels, int width, int minX, int maxX, int minY, int maxY, byte tr, byte tg, byte tb)
		{
			//IL_0054: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_0079: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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)
			//IL_0115: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			minX = Mathf.Clamp(minX, 0, width - 1);
			maxX = Mathf.Clamp(maxX, 0, width - 1);
			minY = Mathf.Clamp(minY, 0, pixels.Length / width - 1);
			maxY = Mathf.Clamp(maxY, 0, pixels.Length / width - 1);
			for (int i = minY; i <= maxY; i++)
			{
				int num = i * width;
				for (int j = minX; j <= maxX; j++)
				{
					int num2 = num + j;
					Color32 val = basePixels[num2];
					if ((Math.Abs(val.r - val.g) >= 5 || Math.Abs(val.g - val.b) >= 5 || val.r <= 160) && (val.r <= 190 || val.g <= 130) && val.r >= 20 && val.r <= 155 && val.g >= 15 && val.g <= 125 && val.b >= 10 && val.b <= 85)
					{
						float num3 = (0.299f * (float)(int)val.r + 0.587f * (float)(int)val.g + 0.114f * (float)(int)val.b) / 75f;
						Color32 val2 = pixels[num2];
						val2.r = (byte)Mathf.Clamp((int)((float)(int)tr * num3), 0, 255);
						val2.g = (byte)Mathf.Clamp((int)((float)(int)tg * num3), 0, 255);
						val2.b = (byte)Mathf.Clamp((int)((float)(int)tb * num3), 0, 255);
						pixels[num2] = val2;
					}
				}
			}
		}

		private static Texture2D MakeReadable(Texture source)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			Graphics.Blit(source, temporary);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, false);
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)temporary).width, (float)((Texture)temporary).height), 0, 0);
			val.Apply(false, false);
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			return val;
		}

		public static void SyncAppearanceOverNetwork(PlayerController player, PlayerHairState hairState)
		{
			//IL_000c: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				string text = BuildCustomId(((object)player.PlayerData.ID/*cast due to .constrained prefix*/).ToString(), hairState);
				string text2 = ((object)player.PlayerData.Username/*cast due to .constrained prefix*/).ToString();
				NetworkPlayerData val = default(NetworkPlayerData);
				((NetworkPlayerData)(ref val))..ctor(text, text2);
				if (RpcDefinePlayerDataMethod != null)
				{
					RpcDefinePlayerDataMethod.Invoke(player, new object[1] { val });
				}
				else
				{
					Traverse.Create((object)player).Method("Rpc_DefinePlayerData", new object[1] { val }).GetValue();
				}
				Plugin.Logger.LogInfo((object)("[Network Sync] Appearance synchronized: (ID: " + text + ")"));
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error syncing appearance over network: {arg}");
			}
		}

		public static void SyncAppearanceOverNetwork(PlayerController player, int hair)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			SyncAppearanceOverNetwork(player, new PlayerHairState(hair, null, GetHairInfo(hair).TargetColor));
		}

		public static void SetCustomHair(string hex, Color32 color)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			PlayerController local = PlayerController.Local;
			if (!((Object)(object)local == (Object)null))
			{
				string text = hex.ToUpper();
				SetSavedHairHex(text);
				PlayerHairState playerHairState = new PlayerHairState(-1, text, color);
				ApplyAppearanceToPlayer(local, playerHairState);
				SyncAppearanceOverNetwork(local, playerHairState);
				CustomizerHUD.ClearError();
				CustomizerHUD.UpdateText();
				Plugin.Logger.LogInfo((object)("[SetCustomHair] Set custom hair color to #" + text));
			}
		}

		public static bool ApplyClipboardHex()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string systemCopyBuffer = GUIUtility.systemCopyBuffer;
				if (string.IsNullOrEmpty(systemCopyBuffer))
				{
					Plugin.Logger.LogWarning((object)"[ApplyClipboardHex] Clipboard is empty.");
					CustomizerHUD.ShowError("Presse-papier vide");
					return false;
				}
				systemCopyBuffer = systemCopyBuffer.Trim();
				if (systemCopyBuffer.Length != 7 || systemCopyBuffer[0] != '#')
				{
					Plugin.Logger.LogWarning((object)"[ApplyClipboardHex] Invalid clipboard format. Expected #RRGGBB (7 characters).");
					CustomizerHUD.ShowError("Format invalide");
					return false;
				}
				string text = systemCopyBuffer.Substring(1);
				if (!TryParseHex(text, out var color))
				{
					Plugin.Logger.LogWarning((object)"[ApplyClipboardHex] Invalid hex characters in clipboard.");
					CustomizerHUD.ShowError("Hex invalide");
					return false;
				}
				if (CurrentElement == CustomizerElement.Hair)
				{
					SetCustomHair(text.ToUpper(), color);
				}
				CustomizerHUD.ClearError();
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("[ApplyClipboardHex] Error applying clipboard hex: " + ex.GetType().Name));
				CustomizerHUD.ShowError("Erreur");
				return false;
			}
		}

		public static bool HasCustomHair(PlayerController player)
		{
			return GetPlayerHairState(player).IsCustom;
		}

		public static void ResetAppearance()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			SetSavedHair(0);
			SetSavedHairHex(string.Empty);
			PlayerController local = PlayerController.Local;
			if ((Object)(object)local != (Object)null)
			{
				PlayerHairState playerHairState = new PlayerHairState(0, null, HairColors[0].TargetColor);
				ApplyAppearanceToPlayer(local, playerHairState);
				SyncAppearanceOverNetwork(local, playerHairState);
			}
			RefreshAllPlayersAppearance();
			CustomizerHUD.ClearError();
			CustomizerHUD.UpdateText();
			Plugin.Logger.LogInfo((object)"Character appearance reset to defaults.");
		}

		public static void ChangeHair(int delta)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			PlayerController local = PlayerController.Local;
			if (!((Object)(object)local == (Object)null) && !HasCustomHair(local))
			{
				int num = HairColors.Length;
				int num2 = (GetSavedHair() + delta) % num;
				if (num2 < 0)
				{
					num2 += num;
				}
				SetSavedHair(num2);
				PlayerHairState playerHairState = new PlayerHairState(num2, null, GetHairInfo(num2).TargetColor);
				ApplyAppearanceToPlayer(local, playerHairState);
				SyncAppearanceOverNetwork(local, playerHairState);
				CustomizerHUD.ClearError();
				CustomizerHUD.UpdateText();
			}
		}

		public static void RefreshAllPlayersAppearance()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerController[] array = Object.FindObjectsOfType<PlayerController>();
				if (array == null)
				{
					return;
				}
				PlayerController[] array2 = array;
				foreach (PlayerController val in array2)
				{
					if (!((Object)(object)val == (Object)null) && !NetworkBool.op_Implicit(val.IsWolf))
					{
						ApplyAppearanceToPlayer(val);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error refreshing all players appearance: {arg}");
			}
		}
	}
	public static class CustomizerHUD
	{
		private static GameObject _hudRoot;

		private static TextMeshProUGUI _headerText;

		private static TextMeshProUGUI _hairText;

		private static TextMeshProUGUI _errorText;

		private static TextMeshProUGUI _controlsText;

		private static Image _hudBg;

		private static Image _hairCircle;

		private static Sprite _circleSprite;

		private static float _errorDismissTime;

		private static Sprite GetOrCreateCircleSprite()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_circleSprite != (Object)null)
			{
				return _circleSprite;
			}
			int num = 64;
			Texture2D val = new Texture2D(num, num, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			float num2 = (float)num / 2f;
			float num3 = ((float)num - 1f) / 2f;
			Color32[] array = (Color32[])(object)new Color32[num * num];
			for (int i = 0; i < num; i++)
			{
				for (int j = 0; j < num; j++)
				{
					float num4 = (float)j - num3;
					float num5 = (float)i - num3;
					float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5);
					if (num6 <= num2 - 2f)
					{
						array[i * num + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
					}
					else if (num6 <= num2)
					{
						float num7 = Mathf.Clamp01(num2 - num6);
						array[i * num + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num7 * 255f));
					}
					else
					{
						array[i * num + j] = new Color32((byte)0, (byte)0, (byte)0, (byte)0);
					}
				}
			}
			val.SetPixels32(array);
			val.Apply();
			_circleSprite = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f);
			return _circleSprite;
		}

		private static Image CreateCircleIndicator(Transform parent, float size = 18f)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_006e: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("CircleShadow", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = size;
			obj.preferredHeight = size;
			obj.minWidth = size;
			obj.minHeight = size;
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(size, size);
			Image component = val.GetComponent<Image>();
			component.sprite = GetOrCreateCircleSprite();
			((Graphic)component).color = new Color(0.12f, 0.14f, 0.2f, 0.95f);
			GameObject val2 = new GameObject("CircleInner", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform component2 = val2.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = new Vector2(1.5f, 1.5f);
			component2.offsetMax = new Vector2(-1.5f, -1.5f);
			Image component3 = val2.GetComponent<Image>();
			component3.sprite = GetOrCreateCircleSprite();
			return component3;
		}

		private static TextMeshProUGUI CreateTextElement(TextMeshProUGUI template, Transform parent, string name)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent);
			((Object)val).name = name;
			Component[] components = val.GetComponents<Component>();
			foreach (Component val2 in components)
			{
				if ((Object)(object)val2 != (Object)null && !(val2 is Transform) && !(val2 is RectTransform) && !(val2 is CanvasRenderer) && !(val2 is TextMeshProUGUI))
				{
					Object.Destroy((Object)(object)val2);
				}
			}
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = true;
				((TMP_Text)component).richText = true;
				((TMP_Text)component).enableAutoSizing = false;
				((TMP_Text)component).enableWordWrapping = false;
				((TMP_Text)component).margin = Vector4.zero;
			}
			return component;
		}

		public static void EnsureInitialized(GameUI gameUI)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Expected O, but got Unknown
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Expected O, but got Unknown
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Expected O, but got Unknown
			if ((Object)(object)_hudRoot != (Object)null || (Object)(object)gameUI == (Object)null)
			{
				return;
			}
			try
			{
				TextMeshProUGUI value = Traverse.Create((object)gameUI).Field<TextMeshProUGUI>("pgmShortcutSkinText").Value;
				if ((Object)(object)value == (Object)null)
				{
					return;
				}
				Transform val = ((Component)gameUI).transform.Find("Canvas");
				if ((Object)(object)val == (Object)null)
				{
					Canvas componentInChildren = ((Component)gameUI).GetComponentInChildren<Canvas>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						val = ((Component)componentInChildren).transform;
					}
				}
				if ((Object)(object)val == (Object)null && (Object)(object)value != (Object)null)
				{
					val = ((TMP_Text)value).transform.parent;
				}
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)gameUI).transform;
				}
				_hudRoot = new GameObject("ReLoupKingHUD", new Type[1] { typeof(RectTransform) });
				_hudRoot.transform.SetParent(val, false);
				_hudRoot.transform.SetAsLastSibling();
				RectTransform component = _hudRoot.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(1f, 0.5f);
				component.anchorMax = new Vector2(1f, 0.5f);
				component.pivot = new Vector2(1f, 0.5f);
				component.anchoredPosition = new Vector2(-40f, 0f);
				component.sizeDelta = new Vector2(330f, 125f);
				GameObject val2 = new GameObject("Border", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				val2.transform.SetParent(_hudRoot.transform, false);
				RectTransform component2 = val2.GetComponent<RectTransform>();
				component2.anchorMin = Vector2.zero;
				component2.anchorMax = Vector2.one;
				component2.offsetMin = Vector2.zero;
				component2.offsetMax = Vector2.zero;
				((Graphic)val2.GetComponent<Image>()).color = new Color(0.22f, 0.25f, 0.35f, 0.65f);
				GameObject val3 = new GameObject("Background", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				val3.transform.SetParent(val2.transform, false);
				RectTransform component3 = val3.GetComponent<RectTransform>();
				component3.anchorMin = Vector2.zero;
				component3.anchorMax = Vector2.one;
				component3.offsetMin = new Vector2(1f, 1f);
				component3.offsetMax = new Vector2(-1f, -1f);
				_hudBg = val3.GetComponent<Image>();
				((Graphic)_hudBg).color = new Color(0.06f, 0.07f, 0.11f, 0.92f);
				VerticalLayoutGroup obj = val3.AddComponent<VerticalLayoutGroup>();
				((LayoutGroup)obj).padding = new RectOffset(16, 16, 12, 12);
				((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f;
				((LayoutGroup)obj).childAlignment = (TextAnchor)0;
				((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
				_headerText = CreateTextElement(value, val3.transform, "HUDHeader");
				((TMP_Text)_headerText).enableAutoSizing = false;
				((TMP_Text)_headerText).fontSize = 12f;
				((TMP_Text)_headerText).alignment = (TextAlignmentOptions)257;
				((TMP_Text)_headerText).text = "<b><color=#FFFFFF>ReLoupKing</color></b>  <size=10><color=#8888AA>v1.0.1</color></size>";
				((Component)_headerText).gameObject.AddComponent<LayoutElement>().preferredHeight = 16f;
				GameObject val4 = new GameObject("HUDMiddleRow", new Type[1] { typeof(RectTransform) });
				val4.transform.SetParent(val3.transform, false);
				HorizontalLayoutGroup obj2 = val4.AddComponent<HorizontalLayoutGroup>();
				((LayoutGroup)obj2).padding = new RectOffset(0, 0, 0, 0);
				((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f;
				((LayoutGroup)obj2).childAlignment = (TextAnchor)3;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
				val4.AddComponent<LayoutElement>().preferredHeight = 22f;
				_hairCircle = CreateCircleIndicator(val4.transform, 16f);
				_hairText = CreateTextElement(value, val4.transform, "HUDHairText");
				((TMP_Text)_hairText).enableAutoSizing = false;
				((TMP_Text)_hairText).fontSize = 13f;
				((TMP_Text)_hairText).alignment = (TextAlignmentOptions)4097;
				LayoutElement obj3 = ((Component)_hairText).gameObject.AddComponent<LayoutElement>();
				obj3.preferredWidth = 135f;
				obj3.preferredHeight = 22f;
				_errorText = CreateTextElement(value, val4.transform, "HUDErrorText");
				((TMP_Text)_errorText).enableAutoSizing = false;
				((TMP_Text)_errorText).enableWordWrapping = false;
				((TMP_Text)_errorText).overflowMode = (TextOverflowModes)0;
				((TMP_Text)_errorText).fontSize = 9.5f;
				((TMP_Text)_errorText).alignment = (TextAlignmentOptions)4097;
				((TMP_Text)_errorText).text = string.Empty;
				LayoutElement obj4 = ((Component)_errorText).gameObject.AddComponent<LayoutElement>();
				obj4.preferredWidth = 130f;
				obj4.preferredHeight = 22f;
				((Component)_errorText).gameObject.SetActive(false);
				_controlsText = CreateTextElement(value, val3.transform, "HUDControlsText");
				((TMP_Text)_controlsText).enableAutoSizing = false;
				((TMP_Text)_controlsText).enableWordWrapping = true;
				((TMP_Text)_controlsText).overflowMode = (TextOverflowModes)0;
				((TMP_Text)_controlsText).fontSize = 9f;
				((TMP_Text)_controlsText).lineSpacing = 2f;
				((TMP_Text)_controlsText).alignment = (TextAlignmentOptions)1025;
				((Component)_controlsText).gameObject.AddComponent<LayoutElement>().preferredHeight = 48f;
				_hudRoot.SetActive(false);
				Plugin.Logger.LogInfo((object)"CustomizerHUD successfully created on native GameUI Canvas with fixed font sizes!");
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error initializing CustomizerHUD: {arg}");
			}
		}

		public static void SetVisible(bool visible, GameUI gameUI = null)
		{
			if ((Object)(object)_hudRoot == (Object)null && visible)
			{
				if ((Object)(object)gameUI == (Object)null && (Object)(object)GameManager.Instance != (Object)null)
				{
					gameUI = GameManager.Instance.gameUI;
				}
				EnsureInitialized(gameUI);
			}
			if ((Object)(object)_hudRoot != (Object)null)
			{
				_hudRoot.SetActive(visible);
				if (visible)
				{
					UpdateText();
				}
				else
				{
					ClearError();
				}
			}
		}

		public static void ShowError(string message, float duration = 3.5f)
		{
			if (!((Object)(object)_hudRoot == (Object)null) && _hudRoot.activeSelf && !((Object)(object)_errorText == (Object)null))
			{
				((TMP_Text)_errorText).text = "<color=#FF5566>" + message + "</color>";
				((Component)_errorText).gameObject.SetActive(true);
				_errorDismissTime = Time.time + duration;
			}
		}

		public static void ClearError()
		{
			if ((Object)(object)_errorText != (Object)null && ((Component)_errorText).gameObject.activeSelf)
			{
				((TMP_Text)_errorText).text = string.Empty;
				((Component)_errorText).gameObject.SetActive(false);
			}
		}

		public static void Tick()
		{
			if ((Object)(object)_errorText != (Object)null && ((Component)_errorText).gameObject.activeSelf && Time.time >= _errorDismissTime)
			{
				ClearError();
			}
		}

		public static void UpdateText()
		{
			//IL_00a6: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_hudRoot == (Object)null || !_hudRoot.activeSelf || (Object)(object)_hairText == (Object)null)
			{
				return;
			}
			try
			{
				PlayerHairState playerHairState = AppearanceManager.GetPlayerHairState(PlayerController.Local);
				if (playerHairState.IsCustom)
				{
					if ((Object)(object)_hairCircle != (Object)null)
					{
						((Graphic)_hairCircle).color = Color32.op_Implicit(playerHairState.Color);
					}
					((TMP_Text)_hairText).text = "Cheveux : #" + playerHairState.CustomHex.ToUpper();
				}
				else
				{
					int presetIndex = playerHairState.PresetIndex;
					int hairCount = AppearanceManager.GetHairCount();
					HairColorInfo hairInfo = AppearanceManager.GetHairInfo(presetIndex);
					if ((Object)(object)_hairCircle != (Object)null)
					{
						((Graphic)_hairCircle).color = Color32.op_Implicit(hairInfo.TargetColor);
					}
					((TMP_Text)_hairText).text = $"Cheveux {presetIndex + 1}/{hairCount}";
				}
				if ((Object)(object)_headerText != (Object)null)
				{
					((TMP_Text)_headerText).text = "<b><color=#FFFFFF>ReLoupKing</color></b>  <size=10><color=#8888AA>v1.0.1</color></size>";
				}
				if ((Object)(object)_controlsText != (Object)null)
				{
					((TMP_Text)_controlsText).text = "<color=#7E8299>" + ((!playerHairState.IsCustom) ? "[Scroll] Changer la couleur\n" : "") + "[K] Coller depuis le presse-papier\n[L] Reset</color>";
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error updating CustomizerHUD text: {arg}");
			}
		}
	}
	[BepInPlugin("com.dev.reloupking", "ReLoupKing", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private static bool _lycansNewRolesHooked;

		private Harmony _harmonyInstance;

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"ReLoupKing v1.0.1 is initializing...");
			try
			{
				_harmonyInstance = new Harmony("com.dev.reloupking");
				_harmonyInstance.PatchAll();
				TryHookLycansNewRoles(_harmonyInstance);
				Logger.LogInfo((object)"Harmony patches applied successfully!");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Failed to apply Harmony patches: {arg}");
			}
		}

		private void Start()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (!_lycansNewRolesHooked)
			{
				Logger.LogInfo((object)"Checking again for LycansNewRoles in Start()...");
				TryHookLycansNewRoles((Harmony)(((object)_harmonyInstance) ?? ((object)new Harmony("com.dev.reloupking"))));
			}
		}

		private void TryHookLycansNewRoles(Harmony harmony)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("LycansNewRoles.PlayerCustom");
				if (type != null)
				{
					_lycansNewRolesHooked = true;
					MethodInfo methodInfo = AccessTools.Method(type, "UpdateColor", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerControllerPatch), "OnLycansNewRolesUpdateColor", (Type[])null, (Type[])null);
						harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"Successfully hooked LycansNewRoles.PlayerCustom.UpdateColor for seamless co-existence!");
					}
					MethodInfo methodInfo3 = AccessTools.Method(type, "UpdateIllusion", new Type[1] { typeof(bool) }, (Type[])null);
					if (methodInfo3 != null)
					{
						MethodInfo methodInfo4 = AccessTools.Method(typeof(PlayerControllerPatch), "OnLycansNewRolesUpdateIllusion", (Type[])null, (Type[])null);
						harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"Successfully hooked LycansNewRoles.PlayerCustom.UpdateIllusion for illusion disguise & restoration!");
					}
					MethodInfo methodInfo5 = AccessTools.Method(type, "UpdateVisible", new Type[1] { typeof(bool) }, (Type[])null);
					if (methodInfo5 != null)
					{
						MethodInfo methodInfo6 = AccessTools.Method(typeof(PlayerControllerPatch), "OnLycansNewRolesUpdateVisible", (Type[])null, (Type[])null);
						harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"Successfully hooked LycansNewRoles.PlayerCustom.UpdateVisible for camouflage restoration!");
					}
				}
				Type type2 = AccessTools.TypeByName("LycansNewRoles.MagicianIllusion");
				if (type2 != null)
				{
					MethodInfo methodInfo7 = AccessTools.Method(type2, "TargetRefChanged", (Type[])null, (Type[])null);
					if (methodInfo7 != null)
					{
						MethodInfo methodInfo8 = AccessTools.Method(typeof(PlayerControllerPatch), "OnLycansNewRolesMagicianIllusion", (Type[])null, (Type[])null);
						harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(methodInfo8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Logger.LogInfo((object)"Successfully hooked LycansNewRoles.MagicianIllusion.TargetRefChanged for decoy appearance sync!");
					}
				}
				Type type3 = AccessTools.TypeByName("LycansNewRoles.UICustomizationComponent");
				if (type3 != null)
				{
					MethodInfo methodInfo9 = AccessTools.Method(type3, "Show", (Type[])null, (Type[])null);
					if (methodInfo9 != null)
					{
						HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(LycansNewRolesPatch), "OnCustomizationShow", (Type[])null, (Type[])null));
						harmony.Patch((MethodBase)methodInfo9, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					MethodInfo methodInfo10 = AccessTools.Method(type3, "Hide", (Type[])null, (Type[])null);
					if (methodInfo10 != null)
					{
						HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(LycansNewRolesPatch), "OnCustomizationHide", (Type[])null, (Type[])null));
						harmony.Patch((MethodBase)methodInfo10, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					Logger.LogInfo((object)"Successfully hooked LycansNewRoles.UICustomizationComponent (Show/Hide) for mirror HUD sync!");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("LycansNewRoles inter-mod check: " + ex.Message));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.dev.reloupking";

		public const string PLUGIN_NAME = "ReLoupKing";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}
namespace ReLoupKing.Patches
{
	[HarmonyPatch(typeof(GameState))]
	public static class GameStatePatch
	{
		[HarmonyPatch("Spawned")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		public static void Spawned_Postfix(GameState __instance)
		{
			try
			{
				StateMachine<EGameState> value = Traverse.Create((object)__instance).Field<StateMachine<EGameState>>("StateMachine").Value;
				if (value != null)
				{
					StateHooks<EGameState> obj = value[(EGameState)2];
					obj.onEnter = (Action<EGameState>)Delegate.Combine(obj.onEnter, (Action<EGameState>)delegate
					{
						TriggerReapply("Play");
					});
					StateHooks<EGameState> obj2 = value[(EGameState)4];
					obj2.onEnter = (Action<EGameState>)Delegate.Combine(obj2.onEnter, (Action<EGameState>)delegate
					{
						TriggerReapply("Meeting");
					});
					StateHooks<EGameState> obj3 = value[(EGameState)1];
					obj3.onEnter = (Action<EGameState>)Delegate.Combine(obj3.onEnter, (Action<EGameState>)delegate
					{
						TriggerReapply("Pregame");
					});
					Plugin.Logger.LogInfo((object)"Successfully hooked GameState StateMachine transitions for appearance persistence!");
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in GameState.Spawned postfix: {arg}");
			}
		}

		private static void TriggerReapply(string stateName)
		{
			Plugin.Logger.LogInfo((object)("[GameState Transition -> " + stateName + "] Reapplying appearances..."));
			ReapplyAllPlayersAppearance();
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedReapply(0.25f));
			}
		}

		private static IEnumerator DelayedReapply(float delaySeconds)
		{
			yield return (object)new WaitForSeconds(delaySeconds);
			ReapplyAllPlayersAppearance();
		}

		public static void ReapplyAllPlayersAppearance()
		{
			AppearanceManager.RefreshAllPlayersAppearance();
		}
	}
	[HarmonyPatch(typeof(GameUI))]
	public static class GameUIPatch
	{
		public static bool IsShortcutSkinActive { get; private set; }

		[HarmonyPatch("ShowPregameShortcutSkin")]
		[HarmonyPostfix]
		public static void ShowPregameShortcutSkin_Postfix(GameUI __instance, bool active)
		{
			IsShortcutSkinActive = active;
			CustomizerHUD.SetVisible(active, __instance);
		}

		public static void UpdateShortcutText(GameUI ui = null)
		{
			CustomizerHUD.UpdateText();
		}
	}
	public static class LycansNewRolesPatch
	{
		public static void OnCustomizationShow()
		{
			try
			{
				CustomizerHUD.SetVisible(visible: true);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in OnCustomizationShow: {arg}");
			}
		}

		public static void OnCustomizationHide()
		{
			try
			{
				CustomizerHUD.SetVisible(visible: false);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in OnCustomizationHide: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	public static class PlayerControllerPatch
	{
		[HarmonyPatch("Rpc_DefinePlayerData")]
		[HarmonyPrefix]
		public static void Rpc_DefinePlayerData_Prefix(PlayerController __instance, ref NetworkPlayerData networkPlayerData)
		{
			//IL_0044: 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)
			try
			{
				if (((SimulationBehaviour)__instance).HasInputAuthority)
				{
					string? text = ((object)networkPlayerData.ID/*cast due to .constrained prefix*/).ToString();
					PlayerHairState savedHairState = AppearanceManager.GetSavedHairState();
					string text2 = AppearanceManager.BuildCustomId(text, savedHairState);
					if (text != text2)
					{
						networkPlayerData = new NetworkPlayerData(text2, ((object)networkPlayerData.Username/*cast due to .constrained prefix*/).ToString());
						Plugin.Logger.LogInfo((object)("Injected custom hair appearance into PlayerData ID: " + text2));
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in Rpc_DefinePlayerData_Prefix: {arg}");
			}
		}

		[HarmonyPatch("OnPlayerDataChanged")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		public static void OnPlayerDataChanged_Postfix(Changed<PlayerController> changed)
		{
			//IL_0014: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerController behaviour = changed.Behaviour;
				if (!((Object)(object)behaviour == (Object)null))
				{
					AppearanceManager.InvalidatePlayerCache(behaviour.Ref);
					AppearanceManager.ApplyAppearanceToPlayer(behaviour);
					Plugin.Logger.LogInfo((object)$"[OnPlayerDataChanged] Re-applied hair appearance to {behaviour.Ref} ({behaviour.PlayerData.Username})");
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in OnPlayerDataChanged_Postfix: {arg}");
			}
		}

		[HarmonyPatch("Despawned")]
		[HarmonyPostfix]
		public static void Despawned_Postfix(PlayerController __instance)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)__instance != (Object)null)
				{
					AppearanceManager.InvalidatePlayerCache(__instance.Ref);
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch("UpdateModel")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		public static void UpdateModel_Postfix(PlayerController __instance, bool isWolf)
		{
			try
			{
				if (!isWolf)
				{
					AppearanceManager.ApplyAppearanceToPlayer(__instance);
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in UpdateModel_Postfix: {arg}");
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void Update_Postfix(PlayerController __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!((SimulationBehaviour)__instance).HasInputAuthority || (int)GameManager.LocalGameState != 1 || (Object)(object)GameManager.Instance == (Object)null || (Object)(object)GameManager.Instance.gameUI == (Object)null || GameManager.Instance.gameUI.IsGameSettingMenuOpen || GameManager.Instance.gameUI.IsSettingMenuOpen || (!PreviewCameraPatch.IsMirrorActive && !GameUIPatch.IsShortcutSkinActive))
				{
					return;
				}
				CustomizerHUD.Tick();
				if (Input.GetKeyDown((KeyCode)107))
				{
					AppearanceManager.ApplyClipboardHex();
				}
				if (!AppearanceManager.HasCustomHair(__instance))
				{
					if (Input.mouseScrollDelta.y > 0.1f)
					{
						AppearanceManager.ChangeHair(1);
					}
					else if (Input.mouseScrollDelta.y < -0.1f)
					{
						AppearanceManager.ChangeHair(-1);
					}
				}
				if (Input.GetKeyDown((KeyCode)108))
				{
					AppearanceManager.ResetAppearance();
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in PlayerController.Update hook: {arg}");
			}
		}

		public static void OnLycansNewRolesUpdateColor(object __instance)
		{
			try
			{
				PlayerController value = Traverse.Create(__instance).Property<PlayerController>("PlayerController", (object[])null).Value;
				if ((Object)(object)value != (Object)null)
				{
					AppearanceManager.ApplyAppearanceToPlayer(value);
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in OnLycansNewRolesUpdateColor: {arg}");
			}
		}

		public static void OnLycansNewRolesUpdateIllusion(object __instance)
		{
			//IL_0028: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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)
			try
			{
				Traverse val = Traverse.Create(__instance);
				PlayerController value = val.Property<PlayerController>("PlayerController", (object[])null).Value;
				if ((Object)(object)value == (Object)null || NetworkBool.op_Implicit(value.IsWolf))
				{
					return;
				}
				PlayerRef value2 = val.Property<PlayerRef>("IllusionTarget", (object[])null).Value;
				PlayerController val2 = (((Object)(object)PlayerController.Local != (Object)null && (Object)(object)PlayerController.Local.LocalCameraHandler != (Object)null) ? PlayerController.Local.LocalCameraHandler.PovPlayer : null);
				bool flag = false;
				if ((Object)(object)val2 != (Object)null)
				{
					try
					{
						Type type = AccessTools.TypeByName("LycansNewRoles.PlayerCustomRegistry");
						if (type != null)
						{
							MethodInfo methodInfo = AccessTools.Method(type, "GetPlayer", new Type[1] { typeof(PlayerRef) }, (Type[])null);
							if (methodInfo != null)
							{
								object obj = methodInfo.Invoke(null, new object[1] { val2.Ref });
								if (obj != null)
								{
									flag = NetworkBool.op_Implicit(Traverse.Create(obj).Property<NetworkBool>("Confused", (object[])null).Value);
								}
							}
						}
					}
					catch
					{
					}
				}
				PlayerController val3 = value;
				if (flag && (Object)(object)val2 != (Object)null)
				{
					val3 = val2;
				}
				else if (value2 != PlayerRef.None && (!((Object)(object)val2 != (Object)null) || !NetworkBool.op_Implicit(val2.PlayerEffectManager.NightVision)))
				{
					val3 = PlayerRegistry.GetPlayer(value2);
					if ((Object)(object)val3 == (Object)null)
					{
						val3 = value;
					}
				}
				if ((Object)(object)val3 != (Object)(object)value)
				{
					PlayerHairState playerHairState = AppearanceManager.GetPlayerHairState(val3);
					int lycansNewRolesOutfitIndex = AppearanceManager.GetLycansNewRolesOutfitIndex(val3.Ref, val3.Index);
					AppearanceManager.ApplyAppearanceToPlayer(value, playerHairState, lycansNewRolesOutfitIndex, updateCache: false);
					Plugin.Logger.LogInfo((object)$"[UpdateIllusion] Applied illusion appearance of {val3.Ref} to {value.Ref}");
				}
				else
				{
					AppearanceManager.ApplyAppearanceToPlayer(value);
					Plugin.Logger.LogInfo((object)$"[UpdateIllusion] Restored appearance for {value.Ref}");
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in OnLycansNewRolesUpdateIllusion: {arg}");
			}
		}

		public static void OnLycansNewRolesUpdateVisible(object __instance, bool visible)
		{
			try
			{
				if (visible)
				{
					OnLycansNewRolesUpdateIllusion(__instance);
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in OnLycansNewRolesUpdateVisible: {arg}");
			}
		}

		public static void OnLycansNewRolesMagicianIllusion(object changed)
		{
			//IL_0030: 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)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object value = Traverse.Create(changed).Property("Behaviour", (object[])null).GetValue();
				if (value == null)
				{
					return;
				}
				PlayerController player = PlayerRegistry.GetPlayer(Traverse.Create(value).Property<PlayerRef>("TargetRef", (object[])null).Value);
				if ((Object)(object)player == (Object)null)
				{
					return;
				}
				SkinnedMeshRenderer value2 = Traverse.Create(value).Field<SkinnedMeshRenderer>("_villagerMeshRenderer").Value;
				if (!((Object)(object)value2 == (Object)null) && !((Object)(object)((Renderer)value2).material == (Object)null))
				{
					PlayerHairState playerHairState = AppearanceManager.GetPlayerHairState(player);
					int lycansNewRolesOutfitIndex = AppearanceManager.GetLycansNewRolesOutfitIndex(player.Ref, player.Index);
					Texture tintedTexture = AppearanceManager.GetTintedTexture(ColorManager.GetTexture(lycansNewRolesOutfitIndex), lycansNewRolesOutfitIndex, playerHairState);
					if ((Object)(object)tintedTexture != (Object)null)
					{
						((Renderer)value2).material.mainTexture = tintedTexture;
						Plugin.Logger.LogInfo((object)$"[MagicianIllusion] Applied custom appearance of {player.Ref} to decoy illusion");
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in OnLycansNewRolesMagicianIllusion: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PreviewCamera))]
	public static class PreviewCameraPatch
	{
		private static bool _mirrorExplicitlyActive;

		public static PreviewCamera CurrentInstance { get; private set; }

		public static bool IsMirrorActive
		{
			get
			{
				if ((!((Object)(object)CurrentInstance != (Object)null) || !CurrentInstance.IsPreviewCameraActive) && !_mirrorExplicitlyActive)
				{
					return GameUIPatch.IsShortcutSkinActive;
				}
				return true;
			}
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake_Postfix(PreviewCamera __instance)
		{
			CurrentInstance = __instance;
		}

		[HarmonyPatch("DisplayPreviewCamera")]
		[HarmonyPostfix]
		public static void DisplayPreviewCamera_Postfix(PreviewCamera __instance, bool active)
		{
			CurrentInstance = __instance;
			_mirrorExplicitlyActive = active;
			if (active)
			{
				CustomizerHUD.UpdateText();
			}
		}

		[HarmonyPatch("DisableCamera")]
		[HarmonyPostfix]
		public static void DisableCamera_Postfix()
		{
			_mirrorExplicitlyActive = false;
			CustomizerHUD.SetVisible(visible: false);
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void Update_Postfix(PreviewCamera __instance)
		{
			CurrentInstance = __instance;
		}
	}
}