Decompiled source of URL Face Items Plus v1.1.0

URLFaceItemsPlus.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using PlayerCustomizationUtils;
using PlayerCustomizationUtils.Extensions;
using RWF;
using RWF.UI;
using TMPro;
using UnboundLib;
using UnboundLib.Networking;
using UnboundLib.Utils.UI;
using UniGif;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
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("URLFaceItemsPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("URLFaceItemsPlus")]
[assembly: AssemblyTitle("URLFaceItemsPlus")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace URLFaceItemsPlus;

public class FaceItem : MonoBehaviour
{
	private static readonly Regex NameRegex = new Regex("URL_(EYES|MOUTH|DETAIL)_(\\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);

	private Player player;

	private SpriteRenderer spriteRenderer;

	private LoadedImage image;

	private int frame;

	private float nextFrameTime;

	private int loadToken;

	private float gifSpeed = 1f;

	private float opacity = 1f;

	public int ItemID { get; private set; } = -1;

	public CharacterItemType ItemType { get; private set; }

	public string Source { get; private set; }

	public bool IsCardChoiceFace { get; private set; }

	private CharacterItem Item => ((Component)this).GetComponent<CharacterItem>();

	private bool ReadIdentification()
	{
		Match match = NameRegex.Match(((Object)((Component)this).gameObject).name);
		if (!match.Success)
		{
			Plugin.LogError("Unable to parse item name '" + ((Object)((Component)this).gameObject).name + "'.");
			return false;
		}
		string text = match.Groups[1].Value.ToLower();
		ItemType = (CharacterItemType)((!(text == "eyes")) ? ((text == "mouth") ? 1 : 2) : 0);
		ItemID = int.Parse(match.Groups[2].Value);
		return true;
	}

	private void Start()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Expected O, but got Unknown
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Expected O, but got Unknown
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		spriteRenderer = ((Component)this).GetComponent<SpriteRenderer>();
		if (!ReadIdentification())
		{
			return;
		}
		if ((Object)(object)((Component)this).transform.root == (Object)(object)((Component)this).transform)
		{
			((Component)this).transform.localScale = Vector3.zero;
			((Component)this).transform.position = 1000000f * Vector3.up;
			return;
		}
		player = ((Component)((Component)this).transform.root).GetComponent<Player>();
		if ((Object)(object)player == (Object)null)
		{
			Transform parent = ((Component)this).transform.parent;
			object obj;
			if (parent == null)
			{
				obj = null;
			}
			else
			{
				Transform parent2 = parent.parent;
				if (parent2 == null)
				{
					obj = null;
				}
				else
				{
					Transform parent3 = parent2.parent;
					obj = ((parent3 != null) ? ((Component)parent3).GetComponent<CardChoiceVisuals>() : null);
				}
			}
			if ((Object)obj != (Object)null && (Object)(object)CardChoice.instance != (Object)null)
			{
				IsCardChoiceFace = true;
				player = ((IEnumerable<Player>)PlayerManager.instance.players).FirstOrDefault((Func<Player, bool>)((Player p) => p.playerID == CardChoice.instance.pickrID));
			}
		}
		if (PhotonNetwork.OfflineMode || PhotonNetwork.CurrentRoom == null || ((Object)(object)player != (Object)null && player.data.view.IsMine))
		{
			ApplyLocalSettings();
			return;
		}
		if ((Object)(object)player != (Object)null)
		{
			if (!FaceItemManager.RemoteItemsEnabled)
			{
				Hide();
				return;
			}
			Type? typeFromHandle = typeof(FaceItem);
			RaiseEventOptions val = new RaiseEventOptions();
			val.TargetActors = new int[1] { player.data.view.OwnerActorNr };
			NetworkingManager.RPC(typeFromHandle, "RPCS_RequestProperties", val, new object[6]
			{
				PhotonNetwork.LocalPlayer.ActorNumber,
				ItemID,
				player.playerID,
				((Object)this).GetInstanceID(),
				(byte)ItemType,
				IsCardChoiceFace
			});
			return;
		}
		Transform parent4 = ((Component)this).transform.parent;
		object obj2;
		if (parent4 == null)
		{
			obj2 = null;
		}
		else
		{
			Transform parent5 = parent4.parent;
			if (parent5 == null)
			{
				obj2 = null;
			}
			else
			{
				Transform parent6 = parent5.parent;
				if (parent6 == null)
				{
					obj2 = null;
				}
				else
				{
					Transform parent7 = parent6.parent;
					if (parent7 == null)
					{
						obj2 = null;
					}
					else
					{
						Transform parent8 = parent7.parent;
						if (parent8 == null)
						{
							obj2 = null;
						}
						else
						{
							Transform parent9 = parent8.parent;
							if (parent9 == null)
							{
								obj2 = null;
							}
							else
							{
								Transform obj3 = parent9.Find("PlayerName");
								obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<TextMeshProUGUI>() : null);
							}
						}
					}
				}
			}
		}
		TextMeshProUGUI val2 = (TextMeshProUGUI)obj2;
		Player val3 = (((Object)(object)val2 != (Object)null) ? FindPlayerByNickname(((TMP_Text)val2).text) : null);
		if (val3 == null)
		{
			Hide();
		}
		else if (val3.IsLocal)
		{
			ApplyLocalSettings();
		}
		else if (FaceItemManager.RemoteItemsEnabled)
		{
			Type? typeFromHandle2 = typeof(FaceItem);
			RaiseEventOptions val = new RaiseEventOptions();
			val.TargetActors = new int[1] { val3.ActorNumber };
			NetworkingManager.RPC(typeFromHandle2, "RPCS_RequestPropertiesByInstance", val, new object[5]
			{
				val3.ActorNumber,
				PhotonNetwork.LocalPlayer.ActorNumber,
				((Object)this).GetInstanceID(),
				ItemID,
				(byte)ItemType
			});
		}
		else
		{
			Hide();
		}
	}

	private void Hide()
	{
		Object.Destroy((Object)(object)((Component)this).gameObject);
	}

	private void ApplyLocalSettings()
	{
		//IL_0008: 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)
		ApplyProperties(FaceItemManager.GetURL(ItemID, ItemType), FaceItemManager.GetLook(ItemID, ItemType), -1);
	}

	private void ApplyProperties(string source, float[] look, int ownerActor)
	{
		if ((Object)(object)Item != (Object)null)
		{
			CharacterItemExtensions.SetScale(Item, L(0, 1f));
			CharacterItemExtensions.SetMoveHealthBarUp(Item, L(1, 0f));
		}
		SetBrightness(L(2, 1f));
		SetOpacity(L(3, 1f));
		SetRotation(L(4, 0f));
		SetGifSpeed(L(5, 1f));
		SetImage(source, ownerActor);
		float L(int i, float def)
		{
			if (look == null || look.Length <= i)
			{
				return def;
			}
			return look[i];
		}
	}

	internal void SetOpacity(float value)
	{
		//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_002f: Unknown result type (might be due to invalid IL or missing references)
		opacity = Mathf.Clamp01(value);
		SpriteRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SpriteRenderer>(true);
		foreach (SpriteRenderer obj in componentsInChildren)
		{
			Color color = obj.color;
			color.a = opacity;
			obj.color = color;
		}
	}

	internal void SetRotation(float degrees)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		((Component)this).transform.localEulerAngles = new Vector3(0f, 0f, degrees);
	}

	internal void SetGifSpeed(float speed)
	{
		gifSpeed = Mathf.Clamp(speed, 0.1f, 30f);
	}

	internal void SetImage(string source, int ownerActor = -1, bool forceRefresh = false)
	{
		Source = source;
		int token = ++loadToken;
		ImageLoader.Load(source, delegate(LoadedImage img)
		{
			if ((Object)(object)this != (Object)null && token == loadToken)
			{
				ShowImage(img);
			}
		}, delegate(string err)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)this == (Object)null) && token == loadToken)
			{
				if (err == "__missing_local__" && ownerActor >= 0 && ownerActor != PhotonNetwork.LocalPlayer.ActorNumber)
				{
					ImageSync.Request(ownerActor, ImageStore.HashFromSource(source), delegate
					{
						if ((Object)(object)this != (Object)null && token == loadToken)
						{
							SetImage(source);
						}
					});
				}
				else if (err != "__missing_local__")
				{
					Plugin.Log($"{ItemType} {ItemID + 1}: {err} ({source})");
				}
			}
		}, forceRefresh);
	}

	private void ShowImage(LoadedImage img)
	{
		image = img;
		frame = 0;
		nextFrameTime = Time.time + img.Delays[0] / gifSpeed;
		if ((Object)(object)spriteRenderer == (Object)null)
		{
			spriteRenderer = ((Component)this).GetComponent<SpriteRenderer>();
		}
		if ((Object)(object)spriteRenderer != (Object)null)
		{
			spriteRenderer.sprite = img.Frames[0];
		}
	}

	internal void SetBrightness(float brightness)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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)
		SpriteRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SpriteRenderer>(true);
		float num = default(float);
		float num2 = default(float);
		float num3 = default(float);
		foreach (SpriteRenderer obj in componentsInChildren)
		{
			Color.RGBToHSV(obj.color, ref num, ref num2, ref num3);
			Color color = Color.HSVToRGB(num, num2, Mathf.Clamp01(brightness));
			color.a = opacity;
			obj.color = color;
		}
	}

	private void Update()
	{
		if (image != null && image.Animated && !(Time.time < nextFrameTime) && !((Object)(object)spriteRenderer == (Object)null))
		{
			int num = 0;
			while (Time.time >= nextFrameTime && num < image.Frames.Length)
			{
				frame = (frame + 1) % image.Frames.Length;
				nextFrameTime += image.Delays[frame] / gifSpeed;
				num++;
			}
			if (nextFrameTime < Time.time)
			{
				nextFrameTime = Time.time + image.Delays[frame] / gifSpeed;
			}
			spriteRenderer.sprite = image.Frames[frame];
		}
	}

	[UnboundRPC]
	private static void RPCS_RequestProperties(int requestingActor, int itemID, int playerID, int instanceID, byte type, bool isCardChoiceFace)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_0077: 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)
		Player val = ((IEnumerable<Player>)PlayerManager.instance.players).FirstOrDefault((Func<Player, bool>)((Player x) => x.playerID == playerID));
		if (!((Object)(object)val == (Object)null) && val.data.view.IsMine)
		{
			CharacterItemType type2 = (CharacterItemType)type;
			Type? typeFromHandle = typeof(FaceItem);
			RaiseEventOptions val2 = new RaiseEventOptions();
			val2.TargetActors = new int[1] { requestingActor };
			NetworkingManager.RPC(typeFromHandle, "RPCA_SetProperties", val2, new object[6]
			{
				FaceItemManager.GetURL(itemID, type2),
				playerID,
				instanceID,
				FaceItemManager.GetLook(itemID, type2),
				isCardChoiceFace,
				PhotonNetwork.LocalPlayer.ActorNumber
			});
		}
	}

	[UnboundRPC]
	private static void RPCS_RequestPropertiesByInstance(int ownerID, int requestingActor, int instanceID, int itemID, byte type)
	{
		//IL_0010: 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_0026: Expected O, but got Unknown
		//IL_0040: 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)
		if (PhotonNetwork.LocalPlayer.ActorNumber == ownerID)
		{
			CharacterItemType type2 = (CharacterItemType)type;
			Type? typeFromHandle = typeof(FaceItem);
			RaiseEventOptions val = new RaiseEventOptions();
			val.TargetActors = new int[1] { requestingActor };
			NetworkingManager.RPC(typeFromHandle, "RPCA_SetPropertiesByInstance", val, new object[4]
			{
				FaceItemManager.GetURL(itemID, type2),
				instanceID,
				FaceItemManager.GetLook(itemID, type2),
				ownerID
			});
		}
	}

	[UnboundRPC]
	private static void RPCA_SetProperties(string url, int playerID, int instanceID, float[] look, bool isCardChoiceFace, int ownerActor)
	{
		object obj2;
		if (!isCardChoiceFace)
		{
			Player? obj = ((IEnumerable<Player>)PlayerManager.instance.players).FirstOrDefault((Func<Player, bool>)((Player p) => p.playerID == playerID));
			obj2 = ((obj != null) ? ((Component)obj).gameObject : null);
		}
		else
		{
			CardChoiceVisuals instance = CardChoiceVisuals.instance;
			obj2 = ((instance != null) ? ((Component)instance).gameObject : null);
		}
		((obj2 != null) ? ((GameObject)obj2).GetComponentsInChildren<FaceItem>(true).FirstOrDefault((FaceItem i) => ((Object)i).GetInstanceID() == instanceID) : null)?.ApplyProperties(url, look, ownerActor);
	}

	[UnboundRPC]
	private static void RPCA_SetPropertiesByInstance(string url, int instanceID, float[] look, int ownerActor)
	{
		Object.FindObjectsOfType<FaceItem>().FirstOrDefault((FaceItem i) => ((Object)i).GetInstanceID() == instanceID)?.ApplyProperties(url, look, ownerActor);
	}

	private static Player FindPlayerByNickname(string nickname)
	{
		if (string.IsNullOrEmpty(nickname) || PhotonNetwork.CurrentRoom == null)
		{
			return null;
		}
		Dictionary<int, Player>.ValueCollection values = PhotonNetwork.CurrentRoom.Players.Values;
		for (int num = nickname.Length; num > 0; num--)
		{
			string candidate = nickname.Substring(0, num);
			Player val = ((IEnumerable<Player>)values).FirstOrDefault((Func<Player, bool>)((Player p) => p.NickName == candidate));
			if (val != null)
			{
				return val;
			}
		}
		return null;
	}
}
public static class FaceItemManager
{
	public const int ItemsPerType = 12;

	public const string DefaultURL = "https://upload.wikimedia.org/wikipedia/commons/5/50/Smile_Image.png";

	public static readonly CharacterItemType[] Types = (CharacterItemType[])(object)new CharacterItemType[3]
	{
		default(CharacterItemType),
		(CharacterItemType)1,
		(CharacterItemType)2
	};

	private static readonly Dictionary<CharacterItemType, FaceItem[]> prefabs = new Dictionary<CharacterItemType, FaceItem[]>();

	private static bool inited;

	public static bool RemoteItemsEnabled
	{
		get
		{
			return PlayerPrefs.GetInt(Key("RemoteURLObjectsEnabled"), 1) == 1;
		}
		set
		{
			PlayerPrefs.SetInt(Key("RemoteURLObjectsEnabled"), value ? 1 : 0);
		}
	}

	public static void Init()
	{
		//IL_001b: 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_0033: 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_0040: Expected O, but got Unknown
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		if (inited)
		{
			return;
		}
		inited = true;
		CharacterItemType[] types = Types;
		foreach (CharacterItemType val in types)
		{
			prefabs[val] = new FaceItem[12];
			for (int j = 0; j < 12; j++)
			{
				GameObject val2 = new GameObject(ItemGameObjectName(j, val));
				Object.DontDestroyOnLoad((Object)(object)val2);
				val2.AddComponent<SpriteRenderer>();
				prefabs[val][j] = val2.AddComponent<FaceItem>();
			}
		}
	}

	public static void AddItemsToCharacterCreator()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < 12; i++)
		{
			CharacterItemType[] types = Types;
			foreach (CharacterItemType val in types)
			{
				CustomCharacterItemManager.AddCustomCharacterItem(((Component)prefabs[val][i]).gameObject, val, 1f, 0f, 1f);
			}
		}
	}

	public static FaceItem GetPrefab(int id, CharacterItemType type)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (id < 0 || id >= 12 || !prefabs.TryGetValue(type, out var value))
		{
			return null;
		}
		return value[id];
	}

	public static string ItemGameObjectName(int id, CharacterItemType type)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return $"URL_{type}_{id}".ToUpper();
	}

	public static string TypeLabel(CharacterItemType type)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Invalid comparison between Unknown and I4
		if ((int)type != 0)
		{
			if ((int)type != 1)
			{
				return "Details";
			}
			return "Mouths";
		}
		return "Eyes";
	}

	private static string Key(string key)
	{
		return "URLCharacterItems_URLItem_" + key;
	}

	private static string Key(int id, CharacterItemType type, string field)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return Key($"{type}{id}{field}");
	}

	public static string GetURL(int id, CharacterItemType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return PlayerPrefs.GetString(Key(id, type, "URL"), "https://upload.wikimedia.org/wikipedia/commons/5/50/Smile_Image.png");
	}

	public static void SetURL(int id, CharacterItemType type, string url)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetString(Key(id, type, "URL"), url);
	}

	public static float GetScale(int id, CharacterItemType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return PlayerPrefs.GetFloat(Key(id, type, "Scale"), 1f);
	}

	public static void SetScale(int id, CharacterItemType type, float v)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetFloat(Key(id, type, "Scale"), v);
	}

	public static float GetBrightness(int id, CharacterItemType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return PlayerPrefs.GetFloat(Key(id, type, "Brightness"), 1f);
	}

	public static void SetBrightness(int id, CharacterItemType type, float v)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetFloat(Key(id, type, "Brightness"), v);
	}

	public static float GetHealthBarOffset(int id, CharacterItemType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return PlayerPrefs.GetFloat(Key(id, type, "HealthBarOffset"), 0f);
	}

	public static void SetHealthBarOffset(int id, CharacterItemType type, float v)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetFloat(Key(id, type, "HealthBarOffset"), v);
	}

	public static float GetOpacity(int id, CharacterItemType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return PlayerPrefs.GetFloat(Key(id, type, "Opacity"), 1f);
	}

	public static void SetOpacity(int id, CharacterItemType type, float v)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetFloat(Key(id, type, "Opacity"), v);
	}

	public static float GetRotation(int id, CharacterItemType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return PlayerPrefs.GetFloat(Key(id, type, "Rotation"), 0f);
	}

	public static void SetRotation(int id, CharacterItemType type, float v)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetFloat(Key(id, type, "Rotation"), v);
	}

	public static float GetGifSpeed(int id, CharacterItemType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return PlayerPrefs.GetFloat(Key(id, type, "GifSpeed"), 1f);
	}

	public static void SetGifSpeed(int id, CharacterItemType type, float v)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetFloat(Key(id, type, "GifSpeed"), v);
	}

	public static float[] GetLook(int id, CharacterItemType type)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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_0027: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		return new float[6]
		{
			GetScale(id, type),
			GetHealthBarOffset(id, type),
			GetBrightness(id, type),
			GetOpacity(id, type),
			GetRotation(id, type),
			GetGifSpeed(id, type)
		};
	}

	public static string DefaultName(int id, CharacterItemType type)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return $"{type} {id + 1}".ToUpper();
	}

	public static string GetName(int id, CharacterItemType type)
	{
		//IL_0001: 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)
		string text = PlayerPrefs.GetString(Key(id, type, "Name"), "");
		if (!string.IsNullOrWhiteSpace(text) && text.Length <= 32)
		{
			return text;
		}
		return DefaultName(id, type);
	}

	public static void SetName(int id, CharacterItemType type, string name)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		PlayerPrefs.SetString(Key(id, type, "Name"), name);
	}

	public static void ResetSlot(int id, CharacterItemType type)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		string[] array = new string[8] { "URL", "Scale", "Brightness", "HealthBarOffset", "Name", "Opacity", "Rotation", "GifSpeed" };
		foreach (string field in array)
		{
			PlayerPrefs.DeleteKey(Key(id, type, field));
		}
	}
}
internal static class FileDialog
{
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
	private class OpenFileName
	{
		public int lStructSize = Marshal.SizeOf(typeof(OpenFileName));

		public IntPtr hwndOwner = IntPtr.Zero;

		public IntPtr hInstance = IntPtr.Zero;

		public string lpstrFilter;

		public string lpstrCustomFilter;

		public int nMaxCustFilter;

		public int nFilterIndex;

		public string lpstrFile;

		public int nMaxFile;

		public string lpstrFileTitle;

		public int nMaxFileTitle;

		public string lpstrInitialDir;

		public string lpstrTitle;

		public int Flags;

		public short nFileOffset;

		public short nFileExtension;

		public string lpstrDefExt;

		public IntPtr lCustData = IntPtr.Zero;

		public IntPtr lpfnHook = IntPtr.Zero;

		public string lpTemplateName;

		public IntPtr pvReserved = IntPtr.Zero;

		public int dwReserved;

		public int FlagsEx;
	}

	private const int OFN_NOCHANGEDIR = 8;

	private const int OFN_PATHMUSTEXIST = 2048;

	private const int OFN_FILEMUSTEXIST = 4096;

	private const int OFN_EXPLORER = 524288;

	private const uint CF_UNICODETEXT = 13u;

	public static bool Supported => Environment.OSVersion.Platform == PlatformID.Win32NT;

	[DllImport("comdlg32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
	private static extern bool GetOpenFileName([In][Out] OpenFileName ofn);

	[DllImport("user32.dll")]
	private static extern IntPtr GetActiveWindow();

	[DllImport("user32.dll")]
	private static extern bool OpenClipboard(IntPtr owner);

	[DllImport("user32.dll")]
	private static extern bool CloseClipboard();

	[DllImport("user32.dll")]
	private static extern IntPtr GetClipboardData(uint format);

	[DllImport("kernel32.dll")]
	private static extern IntPtr GlobalLock(IntPtr mem);

	[DllImport("kernel32.dll")]
	private static extern bool GlobalUnlock(IntPtr mem);

	public static string ReadClipboard()
	{
		if (!Supported || !OpenClipboard(IntPtr.Zero))
		{
			return "";
		}
		try
		{
			IntPtr clipboardData = GetClipboardData(13u);
			if (clipboardData == IntPtr.Zero)
			{
				return "";
			}
			IntPtr intPtr = GlobalLock(clipboardData);
			if (intPtr == IntPtr.Zero)
			{
				return "";
			}
			try
			{
				return Marshal.PtrToStringUni(intPtr) ?? "";
			}
			finally
			{
				GlobalUnlock(clipboardData);
			}
		}
		catch
		{
			return "";
		}
		finally
		{
			CloseClipboard();
		}
	}

	public static string OpenImage()
	{
		if (!Supported)
		{
			return null;
		}
		OpenFileName openFileName = new OpenFileName
		{
			hwndOwner = GetActiveWindow(),
			lpstrFilter = "Images (*.png, *.jpg, *.gif)\0*.png;*.jpg;*.jpeg;*.gif\0All files\0*.*\0\0",
			lpstrFile = new string('\0', 1024),
			nMaxFile = 1024,
			lpstrFileTitle = new string('\0', 256),
			nMaxFileTitle = 256,
			lpstrInitialDir = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
			lpstrTitle = "Choose an image for your character",
			Flags = 530440
		};
		try
		{
			return GetOpenFileName(openFileName) ? openFileName.lpstrFile.TrimEnd(new char[1]) : null;
		}
		catch (Exception ex)
		{
			Plugin.LogError("File dialog failed: " + ex.Message);
			return null;
		}
	}
}
public sealed class LoadedImage
{
	public Sprite[] Frames;

	public float[] Delays;

	public int Width;

	public int Height;

	public string Format;

	public bool Animated => Frames.Length > 1;

	public string Describe()
	{
		if (!Animated)
		{
			return $"{Format}, {Width}x{Height}";
		}
		return $"animated GIF, {Frames.Length} frames, {Width}x{Height}";
	}
}
public static class ImageLoader
{
	private class Waiter
	{
		public Action<LoadedImage> ok;

		public Action<string> fail;
	}

	public const string MissingLocal = "__missing_local__";

	private const int MaxDownloadBytes = 16777216;

	private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36";

	private const string Accept = "image/png,image/jpeg,image/gif;q=0.9,image/*;q=0.5,*/*;q=0.2";

	private static readonly Dictionary<string, LoadedImage> loaded = new Dictionary<string, LoadedImage>();

	private static readonly Dictionary<string, List<Waiter>> pending = new Dictionary<string, List<Waiter>>();

	public static void Load(string source, Action<LoadedImage> ok, Action<string> fail, bool forceRefresh = false)
	{
		if (string.IsNullOrEmpty(source))
		{
			fail?.Invoke("No image set.");
			return;
		}
		LoadedImage value;
		if (forceRefresh)
		{
			loaded.Remove(source);
			if (!ImageStore.IsLocal(source))
			{
				ImageStore.DeleteCache(source);
			}
		}
		else if (loaded.TryGetValue(source, out value))
		{
			ok?.Invoke(value);
			return;
		}
		Waiter item = new Waiter
		{
			ok = ok,
			fail = fail
		};
		if (pending.TryGetValue(source, out var value2))
		{
			value2.Add(item);
			return;
		}
		pending[source] = new List<Waiter> { item };
		((MonoBehaviour)Plugin.instance).StartCoroutine(LoadRoutine(source));
	}

	private static void Finish(string source, LoadedImage img, string error)
	{
		if (img != null)
		{
			loaded[source] = img;
		}
		if (!pending.TryGetValue(source, out var value))
		{
			return;
		}
		pending.Remove(source);
		foreach (Waiter item in value)
		{
			try
			{
				if (img != null)
				{
					item.ok?.Invoke(img);
				}
				else
				{
					item.fail?.Invoke(error);
				}
			}
			catch (Exception ex)
			{
				Plugin.LogError(ex.ToString());
			}
		}
	}

	private static IEnumerator LoadRoutine(string source)
	{
		byte[] bytes = null;
		bool fromWeb = false;
		if (ImageStore.IsLocal(source))
		{
			bytes = ImageStore.ReadUpload(ImageStore.HashFromSource(source));
			if (bytes == null)
			{
				Finish(source, null, "__missing_local__");
				yield break;
			}
		}
		else
		{
			bytes = ImageStore.ReadCache(source);
			if (bytes == null)
			{
				string error = null;
				yield return Download(source, delegate(byte[] b)
				{
					bytes = b;
				}, delegate(string e)
				{
					error = e;
				});
				if (bytes == null)
				{
					Finish(source, null, error);
					yield break;
				}
				fromWeb = true;
			}
		}
		LoadedImage result = null;
		string decodeError = null;
		yield return Decode(bytes, delegate(LoadedImage r)
		{
			result = r;
		}, delegate(string e)
		{
			decodeError = e;
		});
		if (result != null && fromWeb)
		{
			ImageStore.WriteCache(source, bytes);
		}
		if (result == null && !fromWeb && !ImageStore.IsLocal(source))
		{
			ImageStore.DeleteCache(source);
		}
		Finish(source, result, decodeError);
	}

	private static IEnumerator Download(string url, Action<byte[]> ok, Action<string> fail)
	{
		UnityWebRequest www = UnityWebRequest.Get(url);
		try
		{
			www.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36");
			www.SetRequestHeader("Accept", "image/png,image/jpeg,image/gif;q=0.9,image/*;q=0.5,*/*;q=0.2");
			www.timeout = 20;
			yield return www.SendWebRequest();
			if (www.isNetworkError)
			{
				fail("Couldn't reach that site (" + www.error + "). Check the link or your connection.");
				yield break;
			}
			if (www.isHttpError)
			{
				long responseCode = www.responseCode;
				object obj;
				switch (responseCode)
				{
				default:
					obj = $"The site returned an error (HTTP {responseCode}).";
					break;
				case 404L:
					obj = "Nothing found at that link (HTTP 404).";
					break;
				case 401L:
				case 403L:
					obj = $"That site blocks outside downloads (HTTP {responseCode}). Save the image and use UPLOAD FROM PC instead.";
					break;
				}
				fail((string)obj);
				yield break;
			}
			byte[] data = www.downloadHandler.data;
			if (data == null || data.Length == 0)
			{
				fail("The link returned an empty file.");
				yield break;
			}
			if (data.Length > 16777216)
			{
				fail("That image is too large (max 16 MB).");
				yield break;
			}
			ok(data);
		}
		finally
		{
			((IDisposable)www)?.Dispose();
		}
	}

	public static string Sniff(byte[] b)
	{
		if (b == null || b.Length < 12)
		{
			return null;
		}
		if (b[0] == 137 && b[1] == 80 && b[2] == 78 && b[3] == 71)
		{
			return "PNG";
		}
		if (b[0] == byte.MaxValue && b[1] == 216 && b[2] == byte.MaxValue)
		{
			return "JPEG";
		}
		if (b[0] == 71 && b[1] == 73 && b[2] == 70 && b[3] == 56)
		{
			return "GIF";
		}
		if (b[0] == 82 && b[1] == 73 && b[2] == 70 && b[3] == 70 && b[8] == 87 && b[9] == 69 && b[10] == 66 && b[11] == 80)
		{
			return "WEBP";
		}
		if (b[4] == 102 && b[5] == 116 && b[6] == 121 && b[7] == 112)
		{
			return "AVIF";
		}
		if (b[0] == 66 && b[1] == 77)
		{
			return "BMP";
		}
		int i = 0;
		if (b[0] == 239 && b[1] == 187 && b[2] == 191)
		{
			i = 3;
		}
		for (; i < b.Length && i < 64 && char.IsWhiteSpace((char)b[i]); i++)
		{
		}
		if (i < b.Length && b[i] == 60)
		{
			return "HTML";
		}
		return null;
	}

	public static IEnumerator Decode(byte[] bytes, Action<LoadedImage> ok, Action<string> fail)
	{
		string text = Sniff(bytes);
		switch (text)
		{
		case "PNG":
		case "JPEG":
		{
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, bytes, false))
			{
				Object.Destroy((Object)(object)val);
				fail("That file is damaged or not a supported image.");
				break;
			}
			Prepare(val);
			ok(new LoadedImage
			{
				Frames = (Sprite[])(object)new Sprite[1] { MakeSprite(val) },
				Delays = new float[1],
				Width = ((Texture)val).width,
				Height = ((Texture)val).height,
				Format = text
			});
			break;
		}
		case "GIF":
		{
			List<GifTexture> frames = null;
			int w = 0;
			int h = 0;
			yield return UniGif.GetTextureListCoroutine(bytes, (Action<List<GifTexture>, int, int, int>)delegate(List<GifTexture> list, int loops, int width, int height)
			{
				frames = list;
				w = width;
				h = height;
			}, (FilterMode)1, (TextureWrapMode)1, false);
			if (frames == null || frames.Count == 0)
			{
				fail("Couldn't read that GIF.");
				break;
			}
			ok(new LoadedImage
			{
				Frames = frames.Select((GifTexture f) => MakeSprite(f.m_texture2d)).ToArray(),
				Delays = frames.Select((GifTexture f) => (!(f.m_delaySec <= 0.01f)) ? f.m_delaySec : 0.1f).ToArray(),
				Width = w,
				Height = h,
				Format = "GIF"
			});
			break;
		}
		case "WEBP":
		case "AVIF":
			fail("That image is " + text + ", which ROUNDS can't display. Save it as PNG and use UPLOAD FROM PC, or find a .png/.jpg/.gif link.");
			break;
		case "HTML":
			fail("That link is a web page, not an image. Open the image itself, right-click it and choose 'Copy image address'.");
			break;
		default:
			fail((text == null) ? "That isn't an image file ROUNDS can read (use PNG, JPG or GIF)." : (text + " images aren't supported (use PNG, JPG or GIF)."));
			break;
		}
	}

	private static void Prepare(Texture2D tex)
	{
		((Texture)tex).wrapMode = (TextureWrapMode)1;
		((Texture)tex).filterMode = (FilterMode)1;
		tex.Apply(false, true);
	}

	private static Sprite MakeSprite(Texture2D tex)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		return Sprite.Create(tex, new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
	}

	public static string Normalize(string raw)
	{
		if (raw == null)
		{
			return null;
		}
		string text = raw.Trim().Trim('"', '\'', '<', '>', ' ');
		if (text.Length == 0)
		{
			return null;
		}
		if (ImageStore.IsLocal(text))
		{
			return text;
		}
		if (text.StartsWith("//"))
		{
			text = "https:" + text;
		}
		if (!text.Contains("://"))
		{
			text = "https://" + text;
		}
		if (!Uri.TryCreate(text, UriKind.Absolute, out Uri result) || (result.Scheme != "http" && result.Scheme != "https") || !result.Host.Contains("."))
		{
			return null;
		}
		string text2 = result.Host.ToLowerInvariant();
		string absolutePath = result.AbsolutePath;
		if (text2.Contains("google.") && (absolutePath == "/imgres" || absolutePath == "/url"))
		{
			string text3 = Query(result, "imgurl") ?? Query(result, "url") ?? Query(result, "q");
			if (text3 != null && text3.StartsWith("http"))
			{
				return Normalize(text3);
			}
		}
		if (text2.EndsWith("bing.com") && absolutePath.StartsWith("/images"))
		{
			string text4 = Query(result, "mediaurl");
			if (text4 != null)
			{
				return Normalize(text4);
			}
		}
		if ((text2 == "imgur.com" || text2 == "www.imgur.com") && !absolutePath.StartsWith("/a/") && !absolutePath.StartsWith("/gallery/"))
		{
			string text5 = absolutePath.Trim(new char[1] { '/' });
			if (text5.Length > 0 && !text5.Contains("/"))
			{
				return "https://i.imgur.com/" + StripExt(text5) + ".png";
			}
		}
		if (text2 == "i.imgur.com" && (absolutePath.EndsWith(".gifv") || absolutePath.EndsWith(".mp4") || absolutePath.EndsWith(".webm") || absolutePath.EndsWith(".webp")))
		{
			return "https://i.imgur.com/" + StripExt(absolutePath.Trim(new char[1] { '/' })) + ".gif";
		}
		if (text2.EndsWith("giphy.com"))
		{
			string[] array = absolutePath.Trim(new char[1] { '/' }).Split(new char[1] { '/' });
			string text6 = null;
			if (array.Length >= 2 && (array[0] == "gifs" || array[0] == "stickers"))
			{
				text6 = array[1].Split(new char[1] { '-' }).Last();
			}
			else if (array.Length >= 2 && array[0] == "media")
			{
				text6 = array[1];
			}
			else if (text2 == "i.giphy.com" && array.Length == 1)
			{
				text6 = StripExt(array[0]);
			}
			if (!string.IsNullOrEmpty(text6))
			{
				return "https://media.giphy.com/media/" + text6 + "/giphy.gif";
			}
		}
		switch (text2)
		{
		case "media.discordapp.net":
		case "preview.redd.it":
		case "external-preview.redd.it":
			if (result.Query.Contains("format=webp"))
			{
				return result.AbsoluteUri.Replace("format=webp", "format=png");
			}
			break;
		}
		return result.AbsoluteUri;
	}

	private static string StripExt(string s)
	{
		int num = s.LastIndexOf('.');
		if (num <= 0)
		{
			return s;
		}
		return s.Substring(0, num);
	}

	private static string Query(Uri uri, string key)
	{
		string[] array = uri.Query.TrimStart(new char[1] { '?' }).Split(new char[1] { '&' });
		foreach (string text in array)
		{
			int num = text.IndexOf('=');
			if (num > 0 && string.Equals(text.Substring(0, num), key, StringComparison.OrdinalIgnoreCase))
			{
				return Uri.UnescapeDataString(text.Substring(num + 1).Replace('+', ' '));
			}
		}
		return null;
	}

	public static byte[] DecodeDataUri(string s)
	{
		s = s?.Trim();
		if (s == null || !s.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
		{
			return null;
		}
		int num = s.IndexOf(',');
		if (num < 0 || !s.Substring(0, num).EndsWith(";base64", StringComparison.OrdinalIgnoreCase))
		{
			return null;
		}
		try
		{
			return Convert.FromBase64String(s.Substring(num + 1));
		}
		catch
		{
			return null;
		}
	}
}
public static class ImageStore
{
	public const string LocalPrefix = "local:";

	public const int MaxUploadBytes = 3145728;

	private static readonly Regex HashRegex = new Regex("^[0-9a-f]{40}$", RegexOptions.Compiled);

	private static string uploadsDir;

	private static string cacheDir;

	public static void Init()
	{
		string path = Path.Combine(Paths.ConfigPath, "URLFaceItemsPlus");
		uploadsDir = Path.Combine(path, "uploads");
		cacheDir = Path.Combine(path, "cache");
		Directory.CreateDirectory(uploadsDir);
		Directory.CreateDirectory(cacheDir);
	}

	public static string Sha1(byte[] bytes)
	{
		using SHA1 sHA = SHA1.Create();
		byte[] array = sHA.ComputeHash(bytes);
		StringBuilder stringBuilder = new StringBuilder(40);
		byte[] array2 = array;
		foreach (byte b in array2)
		{
			stringBuilder.Append(b.ToString("x2"));
		}
		return stringBuilder.ToString();
	}

	public static bool IsValidHash(string hash)
	{
		if (hash != null)
		{
			return HashRegex.IsMatch(hash);
		}
		return false;
	}

	public static bool IsLocal(string source)
	{
		return source?.StartsWith("local:", StringComparison.Ordinal) ?? false;
	}

	public static string HashFromSource(string source)
	{
		if (!IsLocal(source))
		{
			return null;
		}
		return source.Substring("local:".Length);
	}

	public static string SaveUpload(byte[] bytes)
	{
		string text = Sha1(bytes);
		string path = Path.Combine(uploadsDir, text + ".img");
		if (!File.Exists(path))
		{
			File.WriteAllBytes(path, bytes);
		}
		return "local:" + text;
	}

	public static byte[] ReadUpload(string hash)
	{
		if (!IsValidHash(hash))
		{
			return null;
		}
		string path = Path.Combine(uploadsDir, hash + ".img");
		if (!File.Exists(path))
		{
			return null;
		}
		return File.ReadAllBytes(path);
	}

	public static byte[] ReadCache(string url)
	{
		try
		{
			string path = CachePath(url);
			return File.Exists(path) ? File.ReadAllBytes(path) : null;
		}
		catch
		{
			return null;
		}
	}

	public static void WriteCache(string url, byte[] bytes)
	{
		try
		{
			File.WriteAllBytes(CachePath(url), bytes);
		}
		catch (Exception ex)
		{
			Plugin.LogError("Could not write cache: " + ex.Message);
		}
	}

	public static void DeleteCache(string url)
	{
		try
		{
			File.Delete(CachePath(url));
		}
		catch
		{
		}
	}

	public static int ClearCache()
	{
		int num = 0;
		string[] files = Directory.GetFiles(cacheDir);
		foreach (string path in files)
		{
			try
			{
				File.Delete(path);
				num++;
			}
			catch
			{
			}
		}
		return num;
	}

	private static string CachePath(string url)
	{
		return Path.Combine(cacheDir, Sha1(Encoding.UTF8.GetBytes(url)) + ".img");
	}
}
public static class ImageSync
{
	private class Incoming
	{
		public byte[][] chunks;

		public int received;

		public float requestedAt;

		public readonly List<Action> waiters = new List<Action>();
	}

	private const int ChunkSize = 24576;

	private const int MaxChunks = 129;

	private const int ChunksPerFrame = 2;

	private const float RetryAfter = 20f;

	private static readonly Dictionary<string, Incoming> incoming = new Dictionary<string, Incoming>();

	public static void Request(int ownerActor, string hash, Action onReady)
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Expected O, but got Unknown
		if (!ImageStore.IsValidHash(hash) || PhotonNetwork.OfflineMode || PhotonNetwork.CurrentRoom == null)
		{
			return;
		}
		if (incoming.TryGetValue(hash, out var value))
		{
			value.waiters.Add(onReady);
			if (Time.realtimeSinceStartup - value.requestedAt < 20f)
			{
				return;
			}
			value.chunks = null;
			value.received = 0;
		}
		else
		{
			value = new Incoming();
			value.waiters.Add(onReady);
			incoming[hash] = value;
		}
		value.requestedAt = Time.realtimeSinceStartup;
		Type? typeFromHandle = typeof(ImageSync);
		RaiseEventOptions val = new RaiseEventOptions();
		val.TargetActors = new int[1] { ownerActor };
		NetworkingManager.RPC(typeFromHandle, "RPCS_RequestImage", val, new object[2]
		{
			PhotonNetwork.LocalPlayer.ActorNumber,
			hash
		});
	}

	[UnboundRPC]
	private static void RPCS_RequestImage(int requestingActor, string hash)
	{
		byte[] array = ImageStore.ReadUpload(hash);
		if (array != null && array.Length <= 3145728)
		{
			((MonoBehaviour)Plugin.instance).StartCoroutine(SendChunks(requestingActor, hash, array));
		}
	}

	private static IEnumerator SendChunks(int target, string hash, byte[] bytes)
	{
		int total = (bytes.Length + 24576 - 1) / 24576;
		RaiseEventOptions val = new RaiseEventOptions();
		val.TargetActors = new int[1] { target };
		RaiseEventOptions options = val;
		for (int i = 0; i < total; i++)
		{
			int num = Math.Min(24576, bytes.Length - i * 24576);
			byte[] array = new byte[num];
			Buffer.BlockCopy(bytes, i * 24576, array, 0, num);
			NetworkingManager.RPC(typeof(ImageSync), "RPCA_ImageChunk", options, new object[4] { hash, i, total, array });
			if ((i + 1) % 2 == 0)
			{
				yield return null;
			}
		}
	}

	[UnboundRPC]
	private static void RPCA_ImageChunk(string hash, int index, int total, byte[] data)
	{
		if (!incoming.TryGetValue(hash, out var value) || total <= 0 || total > 129 || index < 0 || index >= total || data == null || data.Length > 24576)
		{
			return;
		}
		if (value.chunks == null || value.chunks.Length != total)
		{
			value.chunks = new byte[total][];
			value.received = 0;
		}
		if (value.chunks[index] != null)
		{
			return;
		}
		value.chunks[index] = data;
		if (++value.received < total)
		{
			return;
		}
		int num = 0;
		byte[][] chunks = value.chunks;
		foreach (byte[] array in chunks)
		{
			num += array.Length;
		}
		byte[] array2 = new byte[num];
		int num2 = 0;
		chunks = value.chunks;
		foreach (byte[] array3 in chunks)
		{
			Buffer.BlockCopy(array3, 0, array2, num2, array3.Length);
			num2 += array3.Length;
		}
		incoming.Remove(hash);
		if (ImageStore.Sha1(array2) != hash)
		{
			Plugin.LogError("Received image failed its integrity check; ignoring.");
			return;
		}
		ImageStore.SaveUpload(array2);
		foreach (Action waiter in value.waiters)
		{
			try
			{
				waiter?.Invoke();
			}
			catch (Exception ex)
			{
				Plugin.LogError(ex.ToString());
			}
		}
	}
}
internal static class OutfitSlots
{
	public const int VanillaCount = 8;

	public const int PageSize = 8;

	public const int TotalCount = 16;

	internal static bool loadingInAwake;

	private static bool selectionRestored;

	private static readonly MethodInfo SelectFaceMethod = AccessTools.Method(typeof(CharacterCreatorHandler), "SelectFace", (Type[])null, (Type[])null);

	private static string SelectedKey(int player)
	{
		return $"URLFaceItemsPlus_SelectedFace{player}";
	}

	internal static void EnsureFaces(CharacterCreatorHandler handler)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		if (!((Object)(object)handler == (Object)null) && handler.playerFaces != null && handler.playerFaces.Length < 16)
		{
			int num = handler.playerFaces.Length;
			PlayerFace[] array = handler.playerFaces;
			Array.Resize(ref array, 16);
			for (int i = num; i < 16; i++)
			{
				array[i] = new PlayerFace();
				array[i].LoadFace(i.ToString());
			}
			handler.playerFaces = array;
		}
	}

	internal static void RestoreSelection(CharacterCreatorHandler handler)
	{
		if (selectionRestored || (Object)(object)handler == (Object)null || handler.selectedFaceID == null || SelectFaceMethod == null)
		{
			return;
		}
		selectionRestored = true;
		for (int i = 0; i < handler.selectedFaceID.Length; i++)
		{
			int num = PlayerPrefs.GetInt(SelectedKey(i), -1);
			if (num >= 8 && num < handler.playerFaces.Length)
			{
				SelectFaceMethod.Invoke(handler, new object[3]
				{
					i,
					handler.playerFaces[num],
					num
				});
			}
		}
	}

	internal static int SavedSelection(int player, int fallback)
	{
		int num = PlayerPrefs.GetInt(SelectedKey(player), -1);
		if (num < 8 || num >= 16)
		{
			return fallback;
		}
		return num;
	}

	internal static void ExpandRowsIn(Component root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		EnsureFaces(CharacterCreatorHandler.instance);
		foreach (Transform item in (from p in root.GetComponentsInChildren<CharacterCreatorPortrait>(true)
			select ((Component)p).transform.parent).Distinct().ToList())
		{
			OutfitRow.Expand(item);
		}
	}

	internal static bool IsLobbyRow(Transform row)
	{
		if (!((Object)(object)((Component)row).GetComponentInParent<CharacterSelectionInstance>() != (Object)null))
		{
			return (Object)(object)((Component)row).GetComponentInParent<PrivateRoomCharacterSelectionInstance>() != (Object)null;
		}
		return true;
	}

	internal static void OnFaceSelected(int player, int faceID)
	{
		if (!loadingInAwake)
		{
			if (faceID >= 8)
			{
				PlayerPrefs.SetInt(SelectedKey(player), faceID);
				PlayerPrefs.SetInt("SelectedFace" + player, 0);
			}
			else
			{
				PlayerPrefs.DeleteKey(SelectedKey(player));
			}
		}
	}
}
[HarmonyPatch(typeof(CharacterCreatorHandler), "Awake")]
internal static class Patch_CharacterCreatorHandler_Awake
{
	private static void Prefix(CharacterCreatorHandler __instance)
	{
		OutfitSlots.loadingInAwake = true;
		OutfitSlots.EnsureFaces(__instance);
	}

	private static void Postfix(CharacterCreatorHandler __instance)
	{
		OutfitSlots.loadingInAwake = false;
		OutfitSlots.RestoreSelection(__instance);
	}

	private static Exception Finalizer(Exception __exception)
	{
		OutfitSlots.loadingInAwake = false;
		return __exception;
	}
}
[HarmonyPatch(typeof(CharacterCreatorHandler), "SelectFace")]
internal static class Patch_CharacterCreatorHandler_SelectFace
{
	private static void Postfix(int __0, int __2)
	{
		OutfitSlots.OnFaceSelected(__0, __2);
	}
}
[HarmonyPatch(typeof(CharacterCreatorPortrait), "Start")]
internal static class Patch_CharacterCreatorPortrait_Start
{
	private static void Prefix(CharacterCreatorPortrait __instance)
	{
		CharacterCreatorHandler instance = CharacterCreatorHandler.instance;
		OutfitSlots.EnsureFaces(instance);
		OutfitSlots.RestoreSelection(instance);
		Transform parent = ((Component)__instance).transform.parent;
		if (OutfitRow.Expand(parent) && !OutfitSlots.IsLobbyRow(parent))
		{
			OutfitPager.Attach(parent);
		}
	}
}
[HarmonyPatch(typeof(CharacterSelectionInstance), "Start")]
internal static class Patch_CharacterSelectionInstance_Start
{
	[HarmonyPriority(800)]
	private static void Prefix(CharacterSelectionInstance __instance)
	{
		OutfitSlots.ExpandRowsIn((Component)(object)__instance);
	}
}
[HarmonyPatch(typeof(CharacterSelectionInstance), "StartPicking")]
internal static class Patch_CharacterSelectionInstance_StartPicking
{
	[HarmonyPriority(800)]
	private static void Prefix(CharacterSelectionInstance __instance)
	{
		OutfitSlots.ExpandRowsIn((Component)(object)__instance);
	}

	private static void Postfix(CharacterSelectionInstance __instance, Player pickingPlayer)
	{
		if ((Object)(object)pickingPlayer != (Object)null)
		{
			__instance.currentlySelectedFace = OutfitSlots.SavedSelection(pickingPlayer.playerID, __instance.currentlySelectedFace);
		}
	}
}
[HarmonyPatch(typeof(PrivateRoomCharacterSelectionInstance), "OnPhotonInstantiate")]
internal static class Patch_RWFPicker_OnPhotonInstantiate
{
	[HarmonyPriority(800)]
	private static void Prefix(PrivateRoomCharacterSelectionInstance __instance)
	{
		OutfitSlots.ExpandRowsIn((Component)(object)__instance);
	}
}
[HarmonyPatch(typeof(PrivateRoomCharacterSelectionInstance), "Start")]
internal static class Patch_RWFPicker_Start
{
	[HarmonyPriority(800)]
	private static void Prefix(PrivateRoomCharacterSelectionInstance __instance)
	{
		OutfitSlots.ExpandRowsIn((Component)(object)__instance);
	}
}
[HarmonyPatch(typeof(PrivateRoomCharacterSelectionInstance), "StartPicking")]
internal static class Patch_RWFPicker_StartPicking
{
	[HarmonyPriority(800)]
	private static void Prefix(PrivateRoomCharacterSelectionInstance __instance)
	{
		OutfitSlots.ExpandRowsIn((Component)(object)__instance);
	}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
internal static class Patch_RWFLobbyCharacter_Ctor
{
	private static void Postfix(LobbyCharacter __instance)
	{
		__instance.faceID = OutfitSlots.SavedSelection(__instance.localID, __instance.faceID);
	}
}
internal class OutfitRow : MonoBehaviour
{
	[SerializeField]
	private bool expanded;

	internal static bool Expand(Transform row)
	{
		if ((Object)(object)row == (Object)null)
		{
			return false;
		}
		OutfitSlots.EnsureFaces(CharacterCreatorHandler.instance);
		OutfitRow component = ((Component)row).GetComponent<OutfitRow>();
		if ((Object)(object)component != (Object)null)
		{
			return component.expanded;
		}
		component = ((Component)row).gameObject.AddComponent<OutfitRow>();
		int num = 0;
		for (int i = 0; i < row.childCount; i++)
		{
			if ((Object)(object)((Component)row.GetChild(i)).GetComponent<CharacterCreatorPortrait>() != (Object)null)
			{
				num++;
			}
		}
		if (num == 16 && row.childCount == 16)
		{
			return component.expanded = true;
		}
		if (num != 8 || row.childCount != 8)
		{
			return component.expanded = false;
		}
		GameObject gameObject = ((Component)row.GetChild(0)).gameObject;
		for (int j = 8; j < 16; j++)
		{
			GameObject obj = Object.Instantiate<GameObject>(gameObject, row, false);
			((Object)obj).name = ((Object)gameObject).name;
			CharacterCreatorPortrait component2 = obj.GetComponent<CharacterCreatorPortrait>();
			CharacterCreatorHandler instance = CharacterCreatorHandler.instance;
			if ((Object)(object)component2 != (Object)null && (Object)(object)instance != (Object)null && instance.playerFaces != null && j < instance.playerFaces.Length)
			{
				component2.myFace = instance.GetFacePreset(j);
			}
		}
		return component.expanded = true;
	}
}
internal class OutfitPager : MonoBehaviour
{
	private RectTransform left;

	private RectTransform right;

	private TextMeshProUGUI pageLabel;

	private GameObject sharedHint;

	private Transform sharedHintParent;

	private Vector3 sharedHintLocalPos;

	private Vector3 sharedHintOffset;

	private bool sharedHintSearched;

	private bool sharedHintMoved;

	public int Page { get; private set; }

	public int PageCount => Mathf.CeilToInt((float)((Component)this).transform.childCount / 8f);

	internal static void Attach(Transform row)
	{
		if (!((Object)(object)row == (Object)null) && !((Object)(object)((Component)row).GetComponent<OutfitPager>() != (Object)null))
		{
			OutfitPager outfitPager = ((Component)row).gameObject.AddComponent<OutfitPager>();
			outfitPager.BuildArrows();
			int valueOrDefault = (CharacterCreatorHandler.instance?.selectedFaceID?.FirstOrDefault()).GetValueOrDefault();
			outfitPager.SetPage(valueOrDefault / 8, fromUser: false);
		}
	}

	public void SetPage(int page, bool fromUser = true)
	{
		Page = Mathf.Clamp(page, 0, PageCount - 1);
		for (int i = 0; i < ((Component)this).transform.childCount; i++)
		{
			((Component)((Component)this).transform.GetChild(i)).gameObject.SetActive(i / 8 == Page);
		}
		if ((Object)(object)left != (Object)null)
		{
			((Component)left).gameObject.SetActive(Page > 0);
		}
		if ((Object)(object)right != (Object)null)
		{
			((Component)right).gameObject.SetActive(Page < PageCount - 1);
		}
		if ((Object)(object)pageLabel != (Object)null)
		{
			((TMP_Text)pageLabel).text = $"{Page + 1}/{PageCount}";
		}
		if (fromUser && (Object)(object)EventSystem.current != (Object)null)
		{
			int num = CharacterCreatorHandler.instance?.selectedFaceID?.FirstOrDefault() ?? (-1);
			int num2 = ((num / 8 == Page) ? num : (Page * 8));
			if (num2 >= 0 && num2 < ((Component)this).transform.childCount)
			{
				EventSystem.current.SetSelectedGameObject(((Component)((Component)this).transform.GetChild(num2)).gameObject);
			}
		}
	}

	private void BuildArrows()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_00ed: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: 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)
		Transform parent = ((Component)this).transform.parent;
		if (!((Object)(object)parent == (Object)null))
		{
			TextMeshProUGUI? obj = ((IEnumerable<TextMeshProUGUI>)((Component)((Component)this).transform.root).GetComponentsInChildren<TextMeshProUGUI>(true)).FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI t) => (Object)(object)((TMP_Text)t).font != (Object)null));
			TMP_FontAsset font = ((obj != null) ? ((TMP_Text)obj).font : null) ?? TMP_Settings.defaultFontAsset;
			Rect rect = ((RectTransform)((Component)this).transform.GetChild(0)).rect;
			float num = Mathf.Max(40f, ((Rect)(ref rect)).height * 0.6f);
			left = MakeArrow("<", parent, font, num, delegate
			{
				SetPage(Page - 1);
			});
			right = MakeArrow(">", parent, font, num, delegate
			{
				SetPage(Page + 1);
			});
			GameObject val = new GameObject("URLFIP_PageLabel", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			val.AddComponent<LayoutElement>().ignoreLayout = true;
			((RectTransform)val.transform).sizeDelta = new Vector2(num * 2f, num * 0.6f);
			pageLabel = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)pageLabel).font = font;
			((TMP_Text)pageLabel).fontSize = num * 0.35f;
			((TMP_Text)pageLabel).alignment = (TextAlignmentOptions)514;
			((Graphic)pageLabel).color = new Color(1f, 1f, 1f, 0.6f);
			((Graphic)pageLabel).raycastTarget = false;
		}
	}

	private static RectTransform MakeArrow(string label, Transform holder, TMP_FontAsset font, float size, Action onClick)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		//IL_0072: 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)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: 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_00db: 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)
		//IL_00e6: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: 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_00fe: 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_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Expected O, but got Unknown
		GameObject val = new GameObject("URLFIP_Arrow" + ((label == "<") ? "Left" : "Right"), new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(holder, false);
		val.AddComponent<LayoutElement>().ignoreLayout = true;
		RectTransform val2 = (RectTransform)val.transform;
		val2.sizeDelta = new Vector2(size, size);
		((Graphic)val.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.001f);
		GameObject val3 = new GameObject("Text", new Type[1] { typeof(RectTransform) });
		val3.transform.SetParent(val.transform, false);
		RectTransform val4 = (RectTransform)val3.transform;
		val4.anchorMin = Vector2.zero;
		val4.anchorMax = Vector2.one;
		Vector2 offsetMin = (val4.offsetMax = Vector2.zero);
		val4.offsetMin = offsetMin;
		TextMeshProUGUI val5 = val3.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val5).text = label;
		((TMP_Text)val5).font = font;
		((TMP_Text)val5).fontSize = size * 0.9f;
		((TMP_Text)val5).alignment = (TextAlignmentOptions)514;
		((Graphic)val5).raycastTarget = false;
		Button obj = val.AddComponent<Button>();
		((Selectable)obj).targetGraphic = (Graphic)(object)val5;
		ColorBlock colors = ((Selectable)obj).colors;
		((ColorBlock)(ref colors)).normalColor = new Color(1f, 1f, 1f, 0.75f);
		((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 0.6f, 0.2f, 1f);
		((ColorBlock)(ref colors)).pressedColor = new Color(1f, 0.45f, 0.1f, 1f);
		((Selectable)obj).colors = colors;
		((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
		{
			onClick();
		});
		return val2;
	}

	private static GameObject FindHintIn(Transform t, Func<Transform, bool> skip = null)
	{
		TextMeshProUGUI[] componentsInChildren = ((Component)t).GetComponentsInChildren<TextMeshProUGUI>(true);
		foreach (TextMeshProUGUI val in componentsInChildren)
		{
			if ((skip == null || !skip(((TMP_Text)val).transform)) && !string.IsNullOrEmpty(((TMP_Text)val).text) && ((TMP_Text)val).text.ToUpperInvariant().Contains("EDIT"))
			{
				Transform parent = ((TMP_Text)val).transform.parent;
				if (!((Object)(object)parent == (Object)null) && !((Object)(object)parent == (Object)(object)t) && !((Object)(object)((Component)parent).GetComponent<CharacterCreatorPortrait>() != (Object)null))
				{
					return ((Component)parent).gameObject;
				}
				return ((Component)val).gameObject;
			}
		}
		return null;
	}

	private bool InsideAnyButton(Transform t)
	{
		for (int i = 0; i < ((Component)this).transform.childCount; i++)
		{
			if (t.IsChildOf(((Component)this).transform.GetChild(i)))
			{
				return true;
			}
		}
		return false;
	}

	private void UpdateEditHint()
	{
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		CharacterCreatorHandler instance = CharacterCreatorHandler.instance;
		int num = (((Object)(object)instance != (Object)null && instance.selectedFaceID != null && instance.selectedFaceID.Length != 0) ? instance.selectedFaceID[0] : (-1));
		bool flag = num >= 0 && num < ((Component)this).transform.childCount && num / 8 == Page;
		if (Page > 0)
		{
			bool flag2 = false;
			for (int i = Page * 8; i < ((Component)this).transform.childCount && i < (Page + 1) * 8; i++)
			{
				GameObject val = FindHintIn(((Component)this).transform.GetChild(i));
				if (!((Object)(object)val == (Object)null))
				{
					flag2 = true;
					bool flag3 = flag && i == num;
					if (val.activeSelf != flag3)
					{
						val.SetActive(flag3);
					}
				}
			}
			if (flag2)
			{
				return;
			}
		}
		if (!sharedHintSearched)
		{
			sharedHintSearched = true;
			Transform val2 = (((Object)(object)((Component)this).transform.parent != (Object)null && (Object)(object)((Component)this).transform.parent.parent != (Object)null) ? ((Component)this).transform.parent.parent : ((Component)this).transform.parent);
			sharedHint = (((Object)(object)val2 != (Object)null) ? FindHintIn(val2, InsideAnyButton) : null);
			if ((Object)(object)sharedHint != (Object)null)
			{
				sharedHintParent = sharedHint.transform.parent;
				sharedHintLocalPos = sharedHint.transform.localPosition;
				Transform val3 = null;
				float num2 = float.MaxValue;
				for (int j = 0; j < Mathf.Min(8, ((Component)this).transform.childCount); j++)
				{
					float num3 = Vector3.Distance(((Component)this).transform.GetChild(j).position, sharedHint.transform.position);
					if (num3 < num2)
					{
						num2 = num3;
						val3 = ((Component)this).transform.GetChild(j);
					}
				}
				sharedHintOffset = (((Object)(object)val3 != (Object)null) ? (sharedHint.transform.position - val3.position) : Vector3.zero);
			}
		}
		if ((Object)(object)sharedHint == (Object)null)
		{
			return;
		}
		if (Page > 0 && flag)
		{
			sharedHint.transform.position = ((Component)this).transform.GetChild(num).position + sharedHintOffset;
			if (!sharedHint.activeSelf)
			{
				sharedHint.SetActive(true);
			}
			sharedHintMoved = true;
		}
		else if (sharedHintMoved)
		{
			sharedHint.transform.SetParent(sharedHintParent, false);
			sharedHint.transform.localPosition = sharedHintLocalPos;
			sharedHintMoved = false;
		}
	}

	private void LateUpdate()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: 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)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: 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)
		//IL_00d4: 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_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		UpdateEditHint();
		if ((Object)(object)left == (Object)null && (Object)(object)right == (Object)null)
		{
			return;
		}
		RectTransform val = (RectTransform)((Component)this).transform;
		float num = float.MaxValue;
		float num2 = float.MinValue;
		float num3 = 0f;
		float num4 = float.MaxValue;
		int num5 = 0;
		for (int i = 0; i < ((Transform)val).childCount; i++)
		{
			Transform child = ((Transform)val).GetChild(i);
			RectTransform val2 = (RectTransform)(object)((child is RectTransform) ? child : null);
			if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeSelf)
			{
				Vector3 localPosition = ((Transform)val2).localPosition;
				Rect rect = val2.rect;
				num = Mathf.Min(num, localPosition.x + ((Rect)(ref rect)).xMin);
				num2 = Mathf.Max(num2, localPosition.x + ((Rect)(ref rect)).xMax);
				num3 += localPosition.y + ((Rect)(ref rect)).center.y;
				num4 = Mathf.Min(num4, localPosition.y + ((Rect)(ref rect)).yMin);
				num5++;
			}
		}
		if (num5 != 0)
		{
			num3 /= (float)num5;
			float num6 = (((Object)(object)left != (Object)null) ? (left.sizeDelta.x * 0.75f) : 40f);
			if ((Object)(object)left != (Object)null)
			{
				((Transform)left).position = ((Transform)val).TransformPoint(new Vector3(num - num6, num3, 0f));
			}
			if ((Object)(object)right != (Object)null)
			{
				((Transform)right).position = ((Transform)val).TransformPoint(new Vector3(num2 + num6, num3, 0f));
			}
			if ((Object)(object)pageLabel != (Object)null)
			{
				((Component)pageLabel).gameObject.SetActive(PageCount > 1);
				((Transform)((TMP_Text)pageLabel).rectTransform).position = ((Transform)val).TransformPoint(new Vector3((num + num2) * 0.5f, num4 - ((TMP_Text)pageLabel).rectTransform.sizeDelta.y * 0.6f, 0f));
			}
		}
	}

	private void OnDisable()
	{
		if ((Object)(object)left != (Object)null)
		{
			((Component)left).gameObject.SetActive(false);
		}
		if ((Object)(object)right != (Object)null)
		{
			((Component)right).gameObject.SetActive(false);
		}
		if ((Object)(object)pageLabel != (Object)null)
		{
			((Component)pageLabel).gameObject.SetActive(false);
		}
	}

	private void OnEnable()
	{
		if (!((Object)(object)left == (Object)null))
		{
			((Component)left).gameObject.SetActive(Page > 0);
			((Component)right).gameObject.SetActive(Page < PageCount - 1);
		}
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInIncompatibility("pykess.rounds.plugins.urlcharacteritems")]
[BepInPlugin("zen.rounds.plugins.urlfaceitemsplus", "URL Face Items Plus", "1.1.0")]
[BepInProcess("Rounds.exe")]
public class Plugin : BaseUnityPlugin
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static UnityAction <>9__7_0;

		internal void <Start>b__7_0()
		{
		}
	}

	public const string ModId = "zen.rounds.plugins.urlfaceitemsplus";

	public const string ModName = "URL Face Items Plus";

	public const string Version = "1.1.0";

	public static Plugin instance;

	internal static void Log(string msg)
	{
		Debug.Log("[URL Face Items Plus] " + msg);
	}

	internal static void LogError(string msg)
	{
		Debug.LogError("[URL Face Items Plus] " + msg);
	}

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		instance = this;
		ImageStore.Init();
		new Harmony("zen.rounds.plugins.urlfaceitemsplus").PatchAll();
	}

	private void Start()
	{
		//IL_0065: 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_0070: Expected O, but got Unknown
		Unbound.RegisterCredits("URL Face Items Plus", new string[2] { "Zen", "Pykess (original URL Face Items)" }, new string[2] { "Original mod", "Support Pykess" }, new string[2] { "https://thunderstore.io/c/rounds/p/Pykess/URL_Face_Items/", "https://ko-fi.com/pykess" });
		object obj = <>c.<>9__7_0;
		if (obj == null)
		{
			UnityAction val = delegate
			{
			};
			<>c.<>9__7_0 = val;
			obj = (object)val;
		}
		Unbound.RegisterMenu("URL Face Items Plus", (UnityAction)obj, (Action<GameObject>)SettingsMenu.Build, (GameObject)null, false);
		FaceItemManager.Init();
		FaceItemManager.AddItemsToCharacterCreator();
	}
}
internal static class SettingsMenu
{
	private class SlotUI
	{
		public int id;

		public CharacterItemType type;

		public TMP_InputField linkField;

		public TextMeshProUGUI status;

		public RectTransform previewTop;

		public RectTransform previewBottom;

		public bool suppress;

		public void Status(string color, string msg)
		{
			if ((Object)(object)status != (Object)null)
			{
				((TMP_Text)status).text = "<color=" + color + ">" + msg + "</color>";
			}
		}

		public void SetLinkText(string text, bool applyNow)
		{
			suppress = true;
			if ((Object)(object)linkField != (Object)null)
			{
				linkField.text = Display(text);
			}
			suppress = false;
			if (applyNow)
			{
				Apply(this, text, forceRefresh: false);
			}
		}
	}

	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static UnityAction <>9__6_1;

		public static UnityAction<bool> <>9__6_2;

		internal void <Build>b__6_1()
		{
		}

		internal void <Build>b__6_2(bool v)
		{
			FaceItemManager.RemoteItemsEnabled = v;
		}
	}

	private const string Good = "#8CE68C";

	private const string Bad = "#FF7A7A";

	private const string Info = "#BBBBBB";

	private static readonly Dictionary<string, List<TextMeshProUGUI>> nameLabels = new Dictionary<string, List<TextMeshProUGUI>>();

	private static FaceItem preview;

	private static Coroutine pendingApply;

	private static readonly Dictionary<string, SlotUI> slots = new Dictionary<string, SlotUI>();

	private static GameObject previewRoot;

	private static GameObject PreviewRoot
	{
		get
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)previewRoot == (Object)null)
			{
				previewRoot = Object.Instantiate<GameObject>(((Component)((Component)CharacterCreatorHandler.instance).transform.GetChild(0).GetChild(1).GetChild(0)).gameObject);
				((Behaviour)((Component)previewRoot.transform.Find("PutItemsUnderHere")).GetComponent<CharacterCreatorDragging>()).enabled = false;
				previewRoot.transform.position = new Vector3(0f, 2.25f, 0f);
				previewRoot.AddComponent<PreviewFollower>();
				Object.DontDestroyOnLoad((Object)(object)previewRoot);
			}
			return previewRoot;
		}
	}

	public static void Build(GameObject menu)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: 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_00df: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Expected O, but got Unknown
		TextMeshProUGUI val = default(TextMeshProUGUI);
		MenuHandler.CreateText("URL Face Items Plus".ToUpper(), menu, ref val, 60, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText("Put any image or GIF on your character", menu, ref val, 30, false, (Color?)new Color(0.75f, 0.75f, 0.75f), (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText(" ", menu, ref val, 20, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		CharacterItemType[] types = FaceItemManager.Types;
		foreach (CharacterItemType type in types)
		{
			string text = FaceItemManager.TypeLabel(type);
			object obj = <>c.<>9__6_1;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
				};
				<>c.<>9__6_1 = val2;
				obj = (object)val2;
			}
			BuildTypeMenu(MenuHandler.CreateMenu(text, (UnityAction)obj, menu, 60, true, true, ((Component)menu.transform.parent).gameObject, true, -1), type);
		}
		MenuHandler.CreateText(" ", menu, ref val, 20, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		bool remoteItemsEnabled = FaceItemManager.RemoteItemsEnabled;
		UnityAction<bool> obj2 = delegate(bool v)
		{
			FaceItemManager.RemoteItemsEnabled = v;
		};
		TextAlignmentOptions? val3 = (TextAlignmentOptions)514;
		MenuHandler.CreateToggle(remoteItemsEnabled, "Show other players' custom items", menu, obj2, 40, true, (Color?)null, (TMP_FontAsset)null, (Material)null, val3);
		TextMeshProUGUI cacheInfo = null;
		MenuHandler.CreateButton("Clear downloaded image cache", menu, (UnityAction)delegate
		{
			int num = ImageStore.ClearCache();
			if ((Object)(object)cacheInfo != (Object)null)
			{
				((TMP_Text)cacheInfo).text = string.Format("<color={0}>Removed {1} cached download(s). They'll re-download when needed.</color>", "#BBBBBB", num);
			}
		}, 35, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText("", menu, ref cacheInfo, 25, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
	}

	private static void BuildTypeMenu(GameObject menu, CharacterItemType type)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: 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_00fb: Expected O, but got Unknown
		//IL_016b: 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)
		TextMeshProUGUI val = default(TextMeshProUGUI);
		MenuHandler.CreateText(FaceItemManager.TypeLabel(type).ToUpper() + " SLOTS", menu, ref val, 50, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText("After setting a slot, add it in the character customizer like any other " + FaceItemManager.TypeLabel(type).ToLower() + ".", menu, ref val, 25, false, (Color?)new Color(0.75f, 0.75f, 0.75f), (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		for (int i = 0; i < 12; i++)
		{
			int id = i;
			string name = FaceItemManager.GetName(id, type);
			GameObject menu2 = MenuHandler.CreateMenu(name, (UnityAction)delegate
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				OpenSlot(id, type);
			}, menu, 45, true, true, ((Component)menu.transform.parent).gameObject, true, -1);
			Transform obj = menu.transform.Find("Group/Grid/Scroll View/Viewport/Content") ?? menu.transform.Find("Group");
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				Transform obj3 = obj.Find(name);
				obj2 = ((obj3 != null) ? ((Component)obj3).GetComponentInChildren<TextMeshProUGUI>() : null);
			}
			TextMeshProUGUI val2 = (TextMeshProUGUI)obj2;
			if ((Object)(object)val2 != (Object)null)
			{
				Labels(id, type).Add(val2);
			}
			BuildSlotMenu(menu2, type, id);
		}
	}

	private static List<TextMeshProUGUI> Labels(int id, CharacterItemType type)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		string key = $"{type}{id}";
		if (!nameLabels.TryGetValue(key, out var value))
		{
			value = (nameLabels[key] = new List<TextMeshProUGUI>());
		}
		return value;
	}

	private static void BuildSlotMenu(GameObject menu, CharacterItemType type, int id)
	{
		//IL_000e: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Expected O, but got Unknown
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Expected O, but got Unknown
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_032a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0433: Unknown result type (might be due to invalid IL or missing references)
		//IL_0439: Invalid comparison between Unknown and I4
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Expected O, but got Unknown
		//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0508: Expected O, but got Unknown
		//IL_0454: Unknown result type (might be due to invalid IL or missing references)
		//IL_0534: Unknown result type (might be due to invalid IL or missing references)
		//IL_053e: Expected O, but got Unknown
		new Color(0.75f, 0.75f, 0.75f);
		SlotUI slot = new SlotUI
		{
			id = id,
			type = type
		};
		slots[$"{type}{id}"] = slot;
		TextMeshProUGUI val = default(TextMeshProUGUI);
		Labels(id, type).Add(MenuHandler.CreateText(FaceItemManager.GetName(id, type), menu, ref val, 42, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null).GetComponentInChildren<TextMeshProUGUI>());
		GameObject val2 = null;
		GameObject val3 = null;
		for (int i = 0; i < 4; i++)
		{
			GameObject val4 = MenuHandler.CreateText(" ", menu, ref val, 44, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			if (i == 0)
			{
				val2 = val4;
			}
			val3 = val4;
		}
		slot.previewTop = val2.GetComponent<RectTransform>();
		slot.previewBottom = val3.GetComponent<RectTransform>();
		MenuHandler.CreateText("", menu, ref slot.status, 22, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		slot.linkField = MenuHandler.CreateInputField(Display(FaceItemManager.GetURL(id, type)), 24, menu, (UnityAction<string>)delegate(string v)
		{
			if (!slot.suppress)
			{
				if (pendingApply != null)
				{
					((MonoBehaviour)Plugin.instance).StopCoroutine(pendingApply);
				}
				pendingApply = ((MonoBehaviour)Plugin.instance).StartCoroutine(ApplyAfterTyping(slot, v));
			}
		}).GetComponentInChildren<TMP_InputField>();
		List<GameObject> list = new List<GameObject> { MenuHandler.CreateButton("Paste link", menu, (UnityAction)delegate
		{
			slot.SetLinkText(FileDialog.ReadClipboard(), applyNow: true);
		}, 26, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null) };
		if (FileDialog.Supported)
		{
			list.Add(MenuHandler.CreateButton("Upload from PC", menu, (UnityAction)delegate
			{
				Upload(slot);
			}, 26, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null));
		}
		list.Add(MenuHandler.CreateButton("Reload", menu, (UnityAction)delegate
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Apply(slot, FaceItemManager.GetURL(id, type), forceRefresh: true);
		}, 26, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null));
		Row(list.ToArray());
		Slider scaleSlider = default(Slider);
		MenuHandler.CreateSlider("Size", menu, 24, 0f, 10f, FaceItemManager.GetScale(id, type), (UnityAction<float>)delegate(float v)
		{
			//IL_0007: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			FaceItemManager.SetScale(id, type, v);
			if ((Object)(object)preview != (Object)null)
			{
				((Component)preview).transform.localScale = Vector3.one * v;
			}
		}, ref scaleSlider, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Slider brightnessSlider = default(Slider);
		MenuHandler.CreateSlider("Brightness", menu, 24, 0f, 1f, FaceItemManager.GetBrightness(id, type), (UnityAction<float>)delegate(float v)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			FaceItemManager.SetBrightness(id, type, v);
			if ((Object)(object)preview != (Object)null)
			{
				preview.SetBrightness(v);
			}
		}, ref brightnessSlider, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Slider opacitySlider = default(Slider);
		MenuHandler.CreateSlider("Opacity", menu, 24, 0f, 1f, FaceItemManager.GetOpacity(id, type), (UnityAction<float>)delegate(float v)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			FaceItemManager.SetOpacity(id, type, v);
			if ((Object)(object)preview != (Object)null)
			{
				preview.SetOpacity(v);
			}
		}, ref opacitySlider, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Slider rotationSlider = default(Slider);
		MenuHandler.CreateSlider("Rotation", menu, 24, -180f, 180f, FaceItemManager.GetRotation(id, type), (UnityAction<float>)delegate(float v)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			FaceItemManager.SetRotation(id, type, v);
			if ((Object)(object)preview != (Object)null)
			{
				preview.SetRotation(v);
			}
		}, ref rotationSlider, true, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Slider gifSpeedSlider = default(Slider);
		MenuHandler.CreateSlider("GIF speed", menu, 24, 0.25f, 30f, FaceItemManager.GetGifSpeed(id, type), (UnityAction<float>)delegate(float v)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			FaceItemManager.SetGifSpeed(id, type, v);
			if ((Object)(object)preview != (Object)null)
			{
				preview.SetGifSpeed(v);
			}
		}, ref gifSpeedSlider, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Slider healthSlider = null;
		if ((int)type == 2)
		{
			MenuHandler.CreateSlider("Raise health bar", menu, 24, 0f, 2f, FaceItemManager.GetHealthBarOffset(id, type), (UnityAction<float>)delegate(float v)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				FaceItemManager.SetHealthBarOffset(id, type, v);
			}, ref healthSlider, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		}
		TMP_InputField nameField = MenuHandler.CreateInputField(FaceItemManager.GetName(id, type), 24, menu, (UnityAction<string>)delegate(string v)
		{
			//IL_001a: 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)
			if (string.IsNullOrWhiteSpace(v) || v.Length > 32)
			{
				return;
			}
			FaceItemManager.SetName(id, type, v);
			foreach (TextMeshProUGUI item in Labels(id, type))
			{
				if ((Object)(object)item != (Object)null)
				{
					((TMP_Text)item).text = v.ToUpper();
				}
			}
		}).GetComponentInChildren<TMP_InputField>();
		MenuHandler.CreateButton("Reset slot", menu, (UnityAction)delegate
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			FaceItemManager.ResetSlot(id, type);
			scaleSlider.value = 1f;
			brightnessSlider.value = 1f;
			opacitySlider.value = 1f;
			rotationSlider.value = 0f;
			gifSpeedSlider.value = 1f;
			if ((Object)(object)healthSlider != (Object)null)
			{
				healthSlider.value = 0f;
			}
			nameField.text = FaceItemManager.DefaultName(id, type);
			slot.SetLinkText("https://upload.wikimedia.org/wikipedia/commons/5/50/Smile_Image.png", applyNow: true);
		}, 24, true, (Color?)new Color(1f, 0.55f, 0.55f), (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		Transform obj = menu.transform.Find("Group/Back");
		if (obj != null)
		{
			Button component = ((Component)obj).GetComponent<Button>();
			if (component != null)
			{
				((UnityEvent)component.onClick).AddListener(new UnityAction(ClosePreview));
			}
		}
	}

	private static void Row(params GameObject[] items)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Expected O, but got Unknown
		if (items.Length == 0 || (Object)(object)items[0] == (Object)null)
		{
			return;
		}
		Transform parent = items[0].transform.parent;
		GameObject val = new GameObject("Row", new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(parent, false);
		val.transform.SetSiblingIndex(items[0].transform.GetSiblingIndex());
		HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>();
		((HorizontalOrVerticalLayoutGroup)obj).spacing = 20f;
		((LayoutGroup)obj).childAlignment = (TextAnchor)4;
		((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
		((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
		((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
		((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
		float num = 0f;
		foreach (GameObject val2 in items)
		{
			if (!((Object)(object)val2 == (Object)null))
			{
				num = Mathf.Max(num, LayoutUtility.GetPreferredHeight(val2.GetComponent<RectTransform>()));
				val2.transform.SetParent(val.transform, false);
				LayoutElement obj2 = val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>();
				obj2.flexibleWidth = 0f;
				obj2.preferredWidth = 300f;
				obj2.minWidth = 0f;
			}
		}
		LayoutElement obj3 = val.AddComponent<LayoutElement>();
		obj3.preferredHeight = Mathf.Max(num, 40f);
		obj3.flexibleWidth = 1f;
	}

	private static string Display(string source)
	{
		if (!ImageStore.IsLocal(source))
		{
			return source;
		}
		return "(uploaded from PC)";
	}

	private static IEnumerator ApplyAfterTyping(SlotUI slot, string text)
	{
		yield return (object)new WaitForSecondsRealtime(0.6f);
		pendingApply = null;
		Apply(slot, text, forceRefresh: false);
	}

	private static void Apply(SlotUI slot, string raw, bool forceRefresh)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (raw == "(uploaded from PC)")
		{
			raw = FaceItemManager.GetURL(slot.id, slot.type);
		}
		byte[] array = ImageLoader.DecodeDataUri(raw);
		string source;
		if (array != null)
		{
			if (array.Length > 3145728)
			{
				slot.Status("#FF7A7A", "That image is too large (max 3 MB).");
				return;
			}
			source = ImageStore.SaveUpload(array);
			slot.SetLinkText(source, applyNow: false);
		}
		else
		{
			source = ImageLoader.Normalize(raw);
			if (source == null)
			{
				slot.Status("#FF7A7A", string.IsNullOrWhiteSpace(raw) ? "Paste an image link or upload a file." : "That doesn't look like a link.");
				return;
			}
			if (source != raw.Trim())
			{
				slot.SetLinkText(source, applyNow: false);
			}
		}
		slot.Status("#BBBBBB", "Loading...");
		ImageLoader.Load(source, delegate(LoadedImage img)
		{
			//IL_0011: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			FaceItemManager.SetURL(slot.id, slot.type, source);
			slot.Status("#8CE68C", "Loaded: " + img.Describe());
			if ((Object)(object)preview != (Object)null && preview.ItemID == slot.id && preview.ItemType == slot.type)
			{
				preview.SetImage(source);
			}
		}, delegate(string err)
		{
			slot.Status("#FF7A7A", (err == "__missing_local__") ? "That uploaded file is missing. Upload it again." : err);
		}, forceRefresh);
	}

	private static void Upload(SlotUI slot)
	{
		string text = FileDialog.OpenImage();
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		byte[] array;
		try
		{
			array = File.ReadAllBytes(text);
		}
		catch (Exception ex)
		{
			slot.Status("#FF7A7A", "Couldn't read that file: " + ex.Message);
			return;
		}
		if (array.Length > 3145728)
		{
			slot.Status("#FF7A7A", $"That file is {(float)array.Length / 1048576f:0.0} MB. Max is 3 MB so other players can receive it.");
			return;
		}
		string text2 = ImageLoader.Sniff(array);
		if (text2 != "PNG" && text2 != "JPEG" && text2 != "GIF")
		{
			slot.Status("#FF7A7A", (text2 == "WEBP" || text2 == "AVIF") ? (text2 + " files can't be shown in ROUNDS. Re-save it as PNG first.") : "Use a PNG, JPG or GIF file.");
		}
		else
		{
			slot.SetLinkText(ImageStore.SaveUpload(array), applyNow: true);
		}
	}

	private static void OpenSlot(int id, CharacterItemType type)
	{
		//IL_002d: 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_0058: 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_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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)
		Transform val = PreviewRoot.transform.Find("PutItemsUnderHere");
		PreviewRoot.SetActive(true);
		ClearChildren(val);
		preview = Object.Instantiate<GameObject>(((Component)FaceItemManager.GetPrefab(id, type)).gameObject, val).GetComponent<FaceItem>();
		((Component)preview).transform.localScale = Vector3.one * FaceItemManager.GetScale(id, type);
		((Component)preview).transform.localPosition = Vector3.zero;
		if (slots.TryGetValue($"{type}{id}", out var slot))
		{
			PreviewFollower component = PreviewRoot.GetComponent<PreviewFollower>();
			component.top = slot.previewTop;
			component.bottom = slot.previewBottom;
			string uRL = FaceItemManager.GetURL(id, type);
			slot.Status("#BBBBBB", "Loading...");
			ImageLoader.Load(uRL, delegate(LoadedImage img)
			{
				slot.Status("#8CE68C", "Loaded: " + img.Describe());
			}, delegate(string err)
			{
				slot.Status("#FF7A7A", (err == "__missing_local__") ? "That uploaded file is missing. Upload it again." : err);
			});
		}
	}

	private static void ClosePreview()
	{
		if (!((Object)(object)previewRoot == (Object)null))
		{
			ClearChildren(previewRoot.transform.Find("PutItemsUnderHere"));
			previewRoot.SetActive(false);
			preview = null;
		}
	}

	private static void ClearChildren(Transform t)
	{
		while (t.childCount > 0)
		{
			Object.DestroyImmediate((Object)(object)((Component)t.GetChild(0)).gameObject);
		}
	}
}
internal class PreviewFollower : MonoBehaviour
{
	public RectTransform top;

	public RectTransform bottom;

	private void LateUpdate()
	{
		//IL_0042: 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_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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		Camera main = Camera.main;
		if (!((Object)(object)top == (Object)null) && !((Object)(object)bottom == (Object)null) && !((Object)(object)main == (Object)null))
		{
			Canvas componentInParent = ((Component)top).GetComponentInParent<Canvas>();
			Camera obj = (((Object)(object)componentInParent == (Object)null || (int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera);
			Vector2 val = RectTransformUtility.WorldToScreenPoint(obj, ((Transform)top).position);
			Vector2 val2 = RectTransformUtility.WorldToScreenPoint(obj, ((Transform)bottom).position);
			Vector2 val3 = (val + val2) * 0.5f;
			float num = ((Component)this).transform.position.z - ((Component)main).transform.position.z;
			Vector3 val4 = main.ScreenToWorldPoint(new Vector3(val3.x, val3.y, num));
			((Component)this).transform.position = new Vector3(val4.x, val4.y, ((Component)this).transform.position.z);
		}
	}
}