Decompiled source of RandomAvatar v1.3.0

Mods/RandomAvatar.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using HarmonyLib;
using Il2CppSLZ.Bonelab;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.SceneStreaming;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using LabFusion;
using LabFusion.Data;
using LabFusion.Entities;
using LabFusion.Network;
using LabFusion.Player;
using LabFusion.SDK.Metadata;
using LabFusion.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using RandomAvatar;
using RandomAvatar.Helper;
using RandomAvatar.Menu;
using RandomAvatar.Menu.Elements;
using RandomAvatar.Patches;
using RandomAvatar.Utilities;
using Semver;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "RandomAvatar", "1.3.0", "HAHOOS", "https://thunderstore.io/c/bonelab/p/HAHOOS/RandomAvatar")]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonColor(0, 255, 0, 255)]
[assembly: MelonAuthorColor(0, 255, 165, 0)]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: AssemblyTitle("Lets you switch to a random avatar by pressing button, as well in other ways")]
[assembly: AssemblyDescription("Lets you switch to a random avatar by pressing button, as well in other ways")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("HAHOOS")]
[assembly: AssemblyProduct("RandomAvatar")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: AssemblyInformationalVersion("1.3.0")]
[assembly: ComVisible(false)]
[assembly: Guid("6c044178-2021-4782-90bf-1dc7b0a93b08")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.3.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RandomAvatar
{
	internal interface IFilterHandler
	{
		Func<AvatarCrate, bool> IsOnList { get; set; }

		bool IsEmpty();

		void SetupPage();
	}
	internal class FilterHandler<T, TConfig> : IFilterHandler where T : class where TConfig : class
	{
		public Func<T, TConfig> GetConfigItem;

		public Func<T, string> GetSearchString;

		public Func<T, string> FetchElementName;

		public Func<T[]> GetItems;

		public Page MainPage { get; internal set; }

		public MelonPreferences_Category Category { get; internal set; }

		public MelonPreferences_Entry<List<TConfig>> List { get; internal set; }

		public bool UseSortMode { get; set; }

		public ViewMode ViewMode { get; set; }

		public SortDirection SortDirection { get; set; }

		public SortMode SortMode { get; set; }

		public string Search { get; set; }

		public string Name { get; set; }

		public Color Color { get; set; }

		public Page Page { get; private set; }

		public Func<AvatarCrate, bool> IsOnList { get; set; }

		public FilterHandler(Page mainPage, MelonPreferences_Category category, string entryName)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			MainPage = mainPage;
			Category = category;
			List = category.CreateEntry<List<TConfig>>(entryName, new List<TConfig>(), (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			UseSortMode = true;
			SortDirection = SortDirection.Descending;
			Search = string.Empty;
			Name = entryName ?? "N/A";
			Color = Color.white;
			base..ctor();
		}

		public void SetupPage()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: 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_0297: Unknown result type (might be due to invalid IL or missing references)
			if (Page == null)
			{
				Page val3 = (Page = MainPage.CreatePage(Name, Color, 10, true));
			}
			BlacklistWhitelist.CleanupPage(Page);
			Page.CreateEnum("Sort Direction", Color.yellow, (Enum)SortDirection, (Action<Enum>)delegate(Enum val)
			{
				SortDirection = (SortDirection)(object)val;
				SetupPage();
			});
			if (UseSortMode)
			{
				Page.CreateEnum("Sort Mode", Color.cyan, (Enum)SortMode, (Action<Enum>)delegate(Enum val)
				{
					SortMode = (SortMode)(object)val;
					SetupPage();
				});
			}
			Page.CreateEnum("View Mode", Color.magenta, (Enum)ViewMode, (Action<Enum>)delegate(Enum val)
			{
				ViewMode = (ViewMode)(object)val;
				SetupPage();
			});
			Page.CreateString("Search", Color.cyan, Search, (Action<string>)delegate(string val)
			{
				Search = val;
				SetupPage();
			});
			Page.CreateFunction("Add All", new Color(0f, 1f, 0f), (Action)delegate
			{
				GetItems().ForEach(delegate(T x)
				{
					ChangeList(x, remove: false);
				});
				SetupPage();
				Category.SaveToFile(false);
			});
			Page.CreateFunction("Remove All", new Color(0f, 1f, 0f), (Action)delegate
			{
				GetItems().ForEach(delegate(T x)
				{
					ChangeList(x, remove: true);
				});
				SetupPage();
				Category.SaveToFile(false);
			});
			Page.CreateFunction("Refresh", Color.yellow, (Action)delegate
			{
				SetupPage();
			});
			if (!UseSortMode)
			{
				Page.CreateBlank();
			}
			Page.CreateBlank();
			Page.CreateLabel("Go to the next page to see all the " + Name.ToLower(), Color.white);
			Page.CreateBlank();
			bool flag = false;
			T[] array = GetItems();
			foreach (T item in array)
			{
				if (item == null)
				{
					return;
				}
				if (!DoesViewModeAllow(((MelonPreferences_Entry<List<?>>)(object)List).Value, GetConfigItem(item), ViewMode) || (!string.IsNullOrWhiteSpace(Search) && !GetSearchString(item).Contains(Search, StringComparison.InvariantCultureIgnoreCase)))
				{
					continue;
				}
				FunctionElement element = null;
				flag = true;
				element = Page.CreateFunction(FetchElementName?.Invoke(item), (Color)(OnList(item) ? new Color(0f, 1f, 0f) : Color.red), (Action)delegate
				{
					//IL_0077: Unknown result type (might be due to invalid IL or missing references)
					//IL_002b: Unknown result type (might be due to invalid IL or missing references)
					if (OnList(item))
					{
						ChangeList(item, remove: true);
						((Element)element).ElementColor = Color.red;
						if (ViewMode == ViewMode.On)
						{
							SetupPage();
						}
					}
					else
					{
						ChangeList(item, remove: false);
						((Element)element).ElementColor = new Color(0f, 1f, 0f);
						if (ViewMode == ViewMode.Off)
						{
							SetupPage();
						}
					}
					Category.SaveToFile(false);
				});
			}
			if (!flag)
			{
				Page.CreateLabel("Nothing to show here :(", Color.white);
			}
		}

		public bool IsEmpty()
		{
			if (((MelonPreferences_Entry<List<?>>)(object)List).Value != null)
			{
				return ((MelonPreferences_Entry<List<?>>)(object)List).Value.Count == 0;
			}
			return true;
		}

		private void ChangeList(T item, bool remove)
		{
			TConfig item2 = GetConfigItem(item);
			if (remove)
			{
				((MelonPreferences_Entry<List<?>>)(object)List).Value.Remove(item2);
			}
			else
			{
				((MelonPreferences_Entry<List<?>>)(object)List).Value.Add(item2);
			}
		}

		private bool OnList(T item)
		{
			TConfig item2 = GetConfigItem(item);
			return ((MelonPreferences_Entry<List<?>>)(object)List).Value.Contains(item2);
		}

		private static bool DoesViewModeAllow(List<TConfig> values, TConfig value, ViewMode mode)
		{
			if (value == null)
			{
				return true;
			}
			if (mode == ViewMode.All)
			{
				return true;
			}
			if (values.Contains(value))
			{
				return mode == ViewMode.On;
			}
			return mode == ViewMode.Off;
		}
	}
	internal static class BlacklistWhitelist
	{
		public static MelonPreferences_Entry<bool> IsWhitelist;

		public static MelonPreferences_Entry<bool> Enabled;

		private static bool mainPageSetup = false;

		public static MelonPreferences_Category Category { get; private set; }

		public static Page Page { get; internal set; }

		public static bool IsSetup { get; private set; } = false;


		internal static List<IFilterHandler> FilterHandlers { get; } = new List<IFilterHandler>();


		public static FilterHandler<AvatarTag, string> TagsHandler { get; private set; }

		public static FilterHandler<AvatarCrate, string> AvatarHandler { get; private set; }

		public static FilterHandler<PalletRef, string> PalletHandler { get; private set; }

		public static void Setup()
		{
			//IL_0108: 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)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			if (IsSetup)
			{
				return;
			}
			IsSetup = true;
			Category = MelonPreferences.CreateCategory("RandomAvatar_BlacklistWhitelist");
			Enabled = Category.CreateEntry<bool>("Enabled", false, "Enabled", "If true, whitelist/blacklist will be checked when changing into random avatar", false, false, (ValueValidator)null, (string)null);
			IsWhitelist = Category.CreateEntry<bool>("IsWhitelist", false, "Is Whitelist", "If true, the avatar will be allowed if it has the tags, if false, it will be allowed only if it doesn't have the tag", false, false, (ValueValidator)null, (string)null);
			TagsHandler = new FilterHandler<AvatarTag, string>(Page, Category, "Tags")
			{
				FetchElementName = (AvatarTag tag) => $"{tag.Tag} [{tag.Count}]",
				GetConfigItem = (AvatarTag tag) => tag.Tag,
				GetItems = GetAllTags,
				GetSearchString = (AvatarTag tag) => tag.Tag,
				Color = Color.cyan,
				UseSortMode = true
			};
			TagsHandler.IsOnList = (AvatarCrate crate) => TagsHandler.List.Value.Any((string x) => ((Crate)crate).Tags.Contains(x));
			FilterHandlers.Add(TagsHandler);
			AvatarHandler = new FilterHandler<AvatarCrate, string>(Page, Category, "Avatars")
			{
				FetchElementName = (AvatarCrate av) => ((Scannable)av).Title ?? "",
				GetConfigItem = (AvatarCrate av) => ((Scannable)av).Barcode.ID,
				GetItems = GetAllAvatars,
				GetSearchString = (AvatarCrate av) => ((Scannable)av).Title,
				Color = Color.magenta,
				UseSortMode = false
			};
			AvatarHandler.IsOnList = (AvatarCrate crate) => AvatarHandler.List.Value.Any((string x) => ((Scannable)crate).Barcode.ID == x);
			FilterHandlers.Add(AvatarHandler);
			PalletHandler = new FilterHandler<PalletRef, string>(Page, Category, "Pallets")
			{
				FetchElementName = (PalletRef pallet) => $"{((Scannable)pallet.Pallet).Title} [{pallet.Avatars.Count}]",
				GetConfigItem = (PalletRef pallet) => ((Scannable)pallet.Pallet).Barcode.ID,
				GetItems = GetAllPallets,
				GetSearchString = (PalletRef pallet) => ((Scannable)pallet.Pallet).Title,
				Color = Color.yellow,
				UseSortMode = true
			};
			PalletHandler.IsOnList = (AvatarCrate crate) => PalletHandler.List.Value.Any((string x) => ((Scannable)((Crate)crate).Pallet).Barcode.ID == x);
			FilterHandlers.Add(PalletHandler);
			Category.SetFilePath(Path.Combine(MelonEnvironment.UserDataDirectory, "RandomAvatar.cfg"));
			Category.SaveToFile(false);
		}

		public static AvatarTag[] GetAllTags()
		{
			if (!AssetWarehouse.ready)
			{
				return Array.Empty<AvatarTag>();
			}
			List<AvatarTag> tags = new List<AvatarTag>();
			AssetWarehouse.Instance.GetCrates<AvatarCrate>((ICrateFilter<AvatarCrate>)null).ForEach(Action<AvatarCrate>.op_Implicit((Action<AvatarCrate>)delegate(AvatarCrate x)
			{
				((Crate)x).Tags.ForEach(Action<string>.op_Implicit((Action<string>)delegate(string y)
				{
					int num = tags.FindIndex((AvatarTag x) => x.Tag == y);
					if (num != -1)
					{
						tags[num].Count++;
					}
					else
					{
						tags.Add(new AvatarTag(y, 1));
					}
				}));
			}));
			if (TagsHandler.SortMode == SortMode.Amount)
			{
				return ((TagsHandler.SortDirection == SortDirection.Ascending) ? tags.OrderBy((AvatarTag x) => x.Count) : tags.OrderByDescending((AvatarTag x) => x.Count)).ToArray();
			}
			return ((TagsHandler.SortDirection == SortDirection.Ascending) ? tags.OrderBy((AvatarTag x) => x.Tag) : tags.OrderByDescending((AvatarTag x) => x.Tag)).ToArray();
		}

		public static AvatarCrate[] GetAllAvatars()
		{
			if (!AssetWarehouse.ready)
			{
				return Array.Empty<AvatarCrate>();
			}
			List<AvatarCrate> crates = AssetWarehouse.Instance.GetCrates<AvatarCrate>((ICrateFilter<AvatarCrate>)null);
			if (!Core.Entry_UseRedacted.Value)
			{
				crates.RemoveAll(Predicate<AvatarCrate>.op_Implicit((Func<AvatarCrate, bool>)((AvatarCrate x) => ((Scannable)x).Redacted)));
			}
			List<AvatarCrate> source = ((IEnumerable<AvatarCrate>)crates.ToArray()).ToList();
			if (AvatarHandler.SortDirection != 0)
			{
				return source.OrderByDescending((AvatarCrate x) => ((Scannable)x).Title).ToArray();
			}
			return source.OrderBy((AvatarCrate x) => ((Scannable)x).Title).ToArray();
		}

		public static PalletRef[] GetAllPallets()
		{
			if (!AssetWarehouse.ready)
			{
				return Array.Empty<PalletRef>();
			}
			List<PalletRef> list = new List<PalletRef>();
			Enumerator<Pallet> enumerator = AssetWarehouse.Instance.GetPallets().GetEnumerator();
			while (enumerator.MoveNext())
			{
				PalletRef palletRef = new PalletRef(enumerator.Current);
				if ((Object)(object)palletRef?.Pallet != (Object)null)
				{
					List<Crate> avatars = palletRef.Avatars;
					if (avatars != null && avatars.Count > 0)
					{
						list.Add(palletRef);
					}
				}
			}
			if (PalletHandler.SortMode == SortMode.Alphabetical)
			{
				if (PalletHandler.SortDirection != 0)
				{
					return list.OrderByDescending((PalletRef x) => ((Scannable)x.Pallet).Title).ToArray();
				}
				return list.OrderBy((PalletRef x) => ((Scannable)x.Pallet).Title).ToArray();
			}
			if (PalletHandler.SortDirection != 0)
			{
				return list.OrderByDescending((PalletRef x) => x.Avatars.Count).ToArray();
			}
			return list.OrderBy((PalletRef x) => x.Avatars.Count).ToArray();
		}

		public static void CleanupPage(Page page)
		{
			page.IndexPages.ForEach(delegate(Page x)
			{
				x.RemoveAll();
				Menu.DestroyPage(x);
			});
			page.RemoveAll();
		}

		public static void RemoveElement(Page page, Element element, bool removeSubPages = true, bool removeMainPage = false)
		{
			if (removeMainPage)
			{
				page.Remove((Element[])(object)new Element[1] { element });
			}
			else
			{
				page.Remove(element);
			}
			page.IndexPages.ForEach(delegate(Page subPage)
			{
				if (subPage != null)
				{
					IReadOnlyList<Element> elements = subPage.Elements;
					if (elements != null && elements.Count > 0)
					{
						if (removeSubPages)
						{
							subPage.Remove((Element[])(object)new Element[1] { element });
						}
						else
						{
							subPage.Remove(element);
						}
					}
				}
			});
		}

		public static void SetupPage()
		{
			//IL_0019: 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)
			if (IsSetup)
			{
				if (!mainPageSetup)
				{
					Page.CreateBoolPref("Enabled", Color.red, ref Enabled, Category);
					Page.CreateBoolPref("Is Whitelist", Color.cyan, ref IsWhitelist, Category);
					Page.CreateBlank();
					mainPageSetup = true;
				}
				FilterHandlers.ForEach(delegate(IFilterHandler x)
				{
					x.SetupPage();
				});
			}
		}

		public static bool IsAvatarAllowed(AvatarCrate crate)
		{
			if ((Object)(object)crate == (Object)null)
			{
				return false;
			}
			if (!IsSetup)
			{
				return true;
			}
			if (!Enabled.Value)
			{
				return true;
			}
			if (FilterHandlers.Any((IFilterHandler x) => x.IsOnList(crate)))
			{
				return IsWhitelist.Value;
			}
			return !IsWhitelist.Value;
		}
	}
	public class AvatarTag
	{
		public string Tag { get; set; }

		public int Count { get; set; }

		public AvatarTag(string tag, int count = 0)
		{
			Tag = tag;
			Count = count;
			base..ctor();
		}
	}
	public enum SortMode
	{
		Amount,
		Alphabetical
	}
	public enum SortDirection
	{
		Ascending,
		Descending
	}
	public enum ViewMode
	{
		All,
		On,
		Off
	}
	internal class PalletRef
	{
		public Pallet Pallet { get; set; }

		public List<Crate> Avatars => Pallet.Crates.FindAll(Predicate<Crate>.op_Implicit((Func<Crate, bool>)((Crate x) => ((MemberInfo)((Object)x).GetIl2CppType()).Name == "AvatarCrate")));

		public PalletRef(Pallet pallet)
		{
			Pallet = pallet;
			base..ctor();
		}
	}
	public class Core : MelonMod
	{
		public const string Version = "1.3.0";

		internal static MelonPreferences_Entry<bool> Entry_UseRedacted;

		internal static MelonPreferences_Entry<bool> Entry_EffectWhenSwitching;

		internal static MelonPreferences_Entry<bool> Entry_AllowRandomAvatarInYourLobbies;

		internal static MelonPreferences_Entry<int> Entry_MinimumFusionDelay;

		internal static MelonPreferences_Category Preferences_Category { get; private set; }

		internal static Instance Logger { get; private set; }

		internal static LevelInfo LevelInfo { get; private set; }

		internal static Dictionary<DateTimeOffset, AvatarCrate> AvatarHistory { get; set; } = new Dictionary<DateTimeOffset, AvatarCrate>();


		public static bool SwapOnDeath { get; internal set; } = false;


		public static bool SwapOnLevelChange { get; internal set; } = false;


		public static bool SwapOnNextLevelChange { get; internal set; } = false;


		public static bool SwapOnDamaged { get; internal set; } = false;


		internal static Thunderstore Thunderstore { get; set; }

		private static bool FirstLoad { get; set; } = true;


		public static void SwapAvatar(string barcode, bool usePCFC)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(barcode) && AssetWarehouse.Instance.HasCrate(new Barcode(barcode)) && !((Object)(object)Player.RigManager == (Object)null))
			{
				if (usePCFC)
				{
					PullCordForceChange obj = ((GameObject)(((object)GameObject.Find("RandomAvatar")) ?? ((object)new GameObject("RandomAvatar")))).AddComponent<PullCordForceChange>();
					obj.avatarCrate = new AvatarCrateReference(barcode);
					obj.rigManager = Player.RigManager;
					obj.ForceChange(((Component)obj.rigManager).gameObject);
				}
				else
				{
					Player.RigManager.SwapAvatarCrate(new Barcode(barcode), true, (Action<bool>)null);
				}
			}
		}

		public static Barcode RandomAvatar()
		{
			if (BlacklistWhitelist.Enabled.Value && BlacklistWhitelist.FilterHandlers.TrueForAll((IFilterHandler x) => x.IsEmpty()))
			{
				BLHelper.SendNotification("Failure", "When having blacklist/whitelist enabled, you need to have at least one tag, avatar and/or pallet selected!", showTitleOnPopup: true, 3f, (NotificationType)2);
				Logger.Error("Cannot swap to random avatar. When having blacklist/whitelist enabled, you need to have at least one tag, avatar and/or pallet selected!");
				return null;
			}
			Random random = new Random();
			List<AvatarCrate> crates = AssetWarehouse.Instance.GetCrates<AvatarCrate>((ICrateFilter<AvatarCrate>)null);
			crates.RemoveAll(Predicate<AvatarCrate>.op_Implicit((Func<AvatarCrate, bool>)delegate(AvatarCrate x)
			{
				if ((Object)(object)x == (Object)null)
				{
					return true;
				}
				if (!Entry_UseRedacted.Value && ((Scannable)x).Redacted)
				{
					return true;
				}
				return (!BlacklistWhitelist.IsAvatarAllowed(x)) ? true : false;
			}));
			AvatarCrate val = crates[random.Next(crates.Count)];
			AvatarHistory.Add(DateTimeOffset.Now, val);
			BoneMenu.SetupHistoryPage();
			return ((Scannable)val).Barcode;
		}

		public static void SwapToRandom()
		{
			if (!AssetWarehouse.ready)
			{
				BLHelper.SendNotification("Failure", "Asset Warehouse is not ready and therefore the avatar cannot be switched", showTitleOnPopup: true, 2f, (NotificationType)2);
				return;
			}
			if (!Fusion.IsAllowed())
			{
				BLHelper.SendNotification("Disallowed", "The host of this server has disabled the usage of RandomAvatar, cannot change you into a random avatar", showTitleOnPopup: true, 3.5f, (NotificationType)2);
				return;
			}
			if ((double)BoneMenu.Cooldown > 1.5)
			{
				BLHelper.SendNotification("Cooldown", $"Wait {BoneMenu.Cooldown} more seconds", showTitleOnPopup: true, 1.5f, (NotificationType)1);
				return;
			}
			Barcode val = RandomAvatar();
			if (!(val == (Barcode)null))
			{
				if (Fusion.IsConnected())
				{
					BoneMenu.Cooldown = BoneMenu.MinimumDelay;
				}
				SwapAvatar(val.ID, Entry_EffectWhenSwitching.Value);
			}
		}

		private void PatchFusion()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(LocalRagdoll).GetMethod("Knockout", new Type[1] { typeof(float) }), (HarmonyMethod)null, new HarmonyMethod(typeof(LocalRagdollPatches).GetMethod("Postfix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(LocalRagdoll).GetMethod("Knockout", new Type[2]
			{
				typeof(float),
				typeof(bool)
			}), (HarmonyMethod)null, new HarmonyMethod(typeof(LocalRagdollPatches).GetMethod("Postfix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)typeof(FusionMod).GetMethod("OnMainSceneInitializeDelayed"), (HarmonyMethod)null, new HarmonyMethod(typeof(FusionPatches).GetMethod("Postfix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public override void OnInitializeMelon()
		{
			Logger = ((MelonBase)this).LoggerInstance;
			try
			{
				Thunderstore = new Thunderstore("RandomAvatar / 1.3.0 A BONELAB Code Mod");
				Thunderstore.BL_FetchPackage("RandomAvatar", "HAHOOS", "1.3.0", ((MelonBase)this).LoggerInstance);
			}
			catch (Exception value)
			{
				((MelonBase)this).LoggerInstance.Error($"An unexpected error has occurred while trying to gather thunderstore package information, exception:\n{value}");
			}
			((MelonBase)this).LoggerInstance.Msg("Setting up preferences");
			Preferences_Category = MelonPreferences.CreateCategory("RandomAvatar");
			Entry_UseRedacted = Preferences_Category.CreateEntry<bool>("UseRedacted", false, "Use Redacted", "If true, when switching to random avatar the mod will also include redacted avatars", false, false, (ValueValidator)null, (string)null);
			Entry_EffectWhenSwitching = Preferences_Category.CreateEntry<bool>("EffectWhenSwitching", true, "Effect When Switching", "If true, when switching to random avatar there will be an effect with the Pull Cord Device like when going into an area in a level that changes your avatar", false, false, (ValueValidator)null, (string)null);
			Entry_AllowRandomAvatarInYourLobbies = Preferences_Category.CreateEntry<bool>("AllowRandomAvatarInYourLobbies", true, "Allow Random Avatar In Your Lobbies", "If true, random avatar will work for players when you create your lobby/server, if false they won't be able to use it on versions after 1.1.0", false, false, (ValueValidator)null, (string)null);
			Entry_MinimumFusionDelay = Preferences_Category.CreateEntry<int>("MinimumFusionDelay", 20, "Minimum Fusion Delay", "The minimum delay value (in seconds) for all players using RandomAvatar on versions after 1.1.0", false, false, (ValueValidator)null, (string)null);
			Preferences_Category.SetFilePath(Path.Combine(MelonEnvironment.UserDataDirectory, "RandomAvatar.cfg"));
			Preferences_Category.SaveToFile(false);
			if (HelperMethods.CheckIfAssemblyLoaded("labfusion"))
			{
				((MelonBase)this).LoggerInstance.Msg("Setting up Fusion");
				PatchFusion();
				Fusion.Setup();
			}
			else
			{
				((MelonBase)this).LoggerInstance.Warning("Fusion was not found");
			}
			((MelonBase)this).LoggerInstance.Msg("Creating BoneMenu");
			BoneMenu.Setup();
			((MelonBase)this).LoggerInstance.Msg("Setting up blacklist/whitelist");
			BlacklistWhitelist.Setup();
			((MelonBase)this).LoggerInstance.Msg("Adding hooks");
			Hooking.OnLevelLoaded += delegate(LevelInfo info)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				LevelInfo = info;
				if (!Fusion.IsConnected())
				{
					LevelLoaded();
				}
			};
			((MelonBase)this).LoggerInstance.Msg("Initialized.");
		}

		internal static void LevelLoaded()
		{
			if (FirstLoad)
			{
				FirstLoad = false;
				Thunderstore.BL_SendNotification();
			}
			if ((SwapOnLevelChange || SwapOnNextLevelChange) && !((Object)(object)PlayerRefs.Instance == (Object)null))
			{
				SwapOnNextLevelChange = false;
				if (PlayerRefs.Instance.HasRefs)
				{
					SwapToRandom();
					return;
				}
				PlayerRefs instance = PlayerRefs.Instance;
				instance.OnRefsComplete += Action.op_Implicit((Action)SwapToRandom);
			}
		}

		public override void OnFixedUpdate()
		{
			TimeUtilities.OnEarlyFixedUpdate();
		}

		public override void OnUpdate()
		{
			TimeUtilities.OnEarlyUpdate();
			BoneMenu.Update();
		}
	}
}
namespace RandomAvatar.Utilities
{
	public static class Fusion
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ServerEvent <>9__10_0;

			public static ServerEvent <>9__10_1;

			public static ServerEvent <>9__10_2;

			internal void <Internal_Setup>b__10_0()
			{
				ServerChanged?.Invoke();
			}

			internal void <Internal_Setup>b__10_1()
			{
				ServerChanged?.Invoke();
			}

			internal void <Internal_Setup>b__10_2()
			{
				ServerChanged?.Invoke();
			}
		}

		internal const string Allow_MetadataKey = "RandomAvatar.Allow";

		internal const string Delay_MetadataKey = "RandomAvatar.Delay";

		internal const int FusionDelay = 20;

		internal const int DefaultDelay = 5;

		internal static Action ServerChanged;

		internal static bool Internal_IsConnected()
		{
			return NetworkInfo.HasServer;
		}

		internal static bool Internal_IsMine(Component comp)
		{
			return (Object)(object)comp.GetComponentInParent<RigManager>() == (Object)(object)Player.RigManager;
		}

		internal static bool IsMine(Component comp)
		{
			if (IsConnected())
			{
				return Internal_IsMine(comp);
			}
			return true;
		}

		internal static void Internal_UpdateMetadata()
		{
			if (Core.Entry_AllowRandomAvatarInYourLobbies != null && NetworkInfo.IsHost && LocalPlayer.Metadata != null)
			{
				LocalPlayer.Metadata.Metadata.TrySetMetadata("RandomAvatar.Allow", Core.Entry_AllowRandomAvatarInYourLobbies.Value.ToString());
				LocalPlayer.Metadata.Metadata.TrySetMetadata("RandomAvatar.Delay", Core.Entry_MinimumFusionDelay.Value.ToString());
			}
		}

		internal static void UpdateMetadata()
		{
			if (IsConnected())
			{
				Internal_UpdateMetadata();
			}
		}

		internal static void Internal_Setup()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0038: 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_0043: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			object obj = <>c.<>9__10_0;
			if (obj == null)
			{
				ServerEvent val = delegate
				{
					ServerChanged?.Invoke();
				};
				<>c.<>9__10_0 = val;
				obj = (object)val;
			}
			MultiplayerHooking.OnJoinedServer += (ServerEvent)obj;
			object obj2 = <>c.<>9__10_1;
			if (obj2 == null)
			{
				ServerEvent val2 = delegate
				{
					ServerChanged?.Invoke();
				};
				<>c.<>9__10_1 = val2;
				obj2 = (object)val2;
			}
			MultiplayerHooking.OnStartedServer += (ServerEvent)obj2;
			object obj3 = <>c.<>9__10_2;
			if (obj3 == null)
			{
				ServerEvent val3 = delegate
				{
					ServerChanged?.Invoke();
				};
				<>c.<>9__10_2 = val3;
				obj3 = (object)val3;
			}
			MultiplayerHooking.OnDisconnected += (ServerEvent)obj3;
		}

		internal static int Internal_GetMinimumDelay()
		{
			if (Core.Entry_MinimumFusionDelay == null)
			{
				return 5;
			}
			if (!NetworkInfo.HasServer)
			{
				return 5;
			}
			NetworkPlayer val = default(NetworkPlayer);
			if (!NetworkPlayerManager.TryGetPlayer((byte)0, ref val))
			{
				return 5;
			}
			PlayerMetadata metadata = val.PlayerID.Metadata;
			if (metadata != null)
			{
				NetworkMetadata metadata2 = metadata.Metadata;
				if (metadata2 != null)
				{
					string s = default(string);
					metadata2.TryGetMetadata("RandomAvatar.Delay", ref s);
					if (0 == 0)
					{
						if (!int.TryParse(s, out var result))
						{
							return 20;
						}
						return result;
					}
				}
			}
			return 20;
		}

		internal static int GetMinimumDelay()
		{
			if (!IsConnected())
			{
				return 5;
			}
			return Internal_GetMinimumDelay();
		}

		internal static void Setup()
		{
			if (IsConnected())
			{
				Internal_Setup();
			}
		}

		internal static bool Internal_IsAllowed()
		{
			NetworkPlayer val = default(NetworkPlayer);
			if (!NetworkPlayerManager.TryGetPlayer((byte)0, ref val))
			{
				return true;
			}
			PlayerMetadata metadata = val.PlayerID.Metadata;
			if (metadata != null)
			{
				NetworkMetadata metadata2 = metadata.Metadata;
				if (metadata2 != null)
				{
					string value = default(string);
					metadata2.TryGetMetadata("RandomAvatar.Allow", ref value);
					if (0 == 0)
					{
						if (!bool.TryParse(value, out var result))
						{
							return true;
						}
						return result;
					}
				}
			}
			return true;
		}

		public static bool IsAllowed()
		{
			if (!IsConnected())
			{
				return true;
			}
			return Internal_IsAllowed();
		}

		internal static void Internal_EnsureSync()
		{
			if (NetworkInfo.IsHost)
			{
				if (IsAllowed() != Core.Entry_AllowRandomAvatarInYourLobbies.Value)
				{
					UpdateMetadata();
				}
				else if (GetMinimumDelay() != Core.Entry_MinimumFusionDelay.Value)
				{
					UpdateMetadata();
				}
			}
		}

		public static void EnsureSync()
		{
			if (IsConnected())
			{
				Internal_EnsureSync();
			}
		}

		public static bool IsConnected()
		{
			if (HelperMethods.CheckIfAssemblyLoaded("labfusion"))
			{
				return Internal_IsConnected();
			}
			return false;
		}
	}
	public class Thunderstore
	{
		public readonly string UserAgent;

		private Package _fetchedPackage;

		private bool _isLatestVersion;

		private string _currentVersion;

		public bool IsV1Deprecated { get; set; }

		public Thunderstore(string userAgent)
		{
			UserAgent = userAgent;
		}

		public Thunderstore(string userAgent, bool isV1Deprecated)
			: this(userAgent)
		{
			IsV1Deprecated = isV1Deprecated;
		}

		public Thunderstore()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			if (executingAssembly != null)
			{
				AssemblyName name = executingAssembly.GetName();
				if (name != null)
				{
					UserAgent = $"{name.Name} / {name.Version} C# Application";
				}
			}
		}

		public Thunderstore(bool isV1Deprecated)
		{
			IsV1Deprecated = isV1Deprecated;
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			if (executingAssembly != null)
			{
				AssemblyName name = executingAssembly.GetName();
				if (name != null)
				{
					UserAgent = $"{name.Name} / {name.Version}";
				}
			}
		}

		public void BL_FetchPackage(string name, string author, string currentVersion, Instance logger = null)
		{
			if (_fetchedPackage != null)
			{
				return;
			}
			_currentVersion = currentVersion;
			try
			{
				_fetchedPackage = GetPackage(author, name);
				if (_fetchedPackage == null && logger != null)
				{
					logger.Warning("Could not find Thunderstore package for " + name);
				}
				if (string.IsNullOrWhiteSpace(_fetchedPackage.Latest?.Version) && logger != null)
				{
					logger.Warning("Latest version could not be found or the version is empty");
				}
				_isLatestVersion = _fetchedPackage.IsLatestVersion(currentVersion);
				if (!_isLatestVersion)
				{
					if (logger != null)
					{
						logger.Warning($"A new version of {name} is available: v{_fetchedPackage.Latest.Version} while the current is v{currentVersion}. It is recommended that you update");
					}
				}
				else if (SemVersion.Parse(currentVersion, false) == _fetchedPackage.Latest.SemanticVersion)
				{
					if (logger != null)
					{
						logger.Msg($"Latest version of {name} is installed! (v{currentVersion})");
					}
				}
				else if (logger != null)
				{
					logger.Msg($"Beta release of {name} is installed (v{_fetchedPackage.Latest.Version} is newest, v{currentVersion} is installed)");
				}
			}
			catch (ThunderstorePackageNotFoundException)
			{
				if (logger != null)
				{
					logger.Warning("Could not find Thunderstore package for " + name);
				}
			}
			catch (Exception ex2)
			{
				if (logger != null)
				{
					logger.Error("An unexpected error has occurred while trying to check if " + name + " is the latest version", ex2);
				}
			}
		}

		public void BL_CreateMenuLabel(Page page, bool createBlankSpace = true)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (_fetchedPackage != null)
			{
				if (createBlankSpace)
				{
					((Element)page.CreateFunction("", Color.white, (Action)null)).SetProperty((ElementProperties)1);
				}
				((Element)page.CreateFunction("Current Version: v" + _currentVersion + ((_isLatestVersion || _fetchedPackage == null) ? string.Empty : "<br><color=#00FF00>(Update available!)</color>"), Color.white, (Action)null)).SetProperty((ElementProperties)1);
			}
		}

		public void BL_SendNotification()
		{
			//IL_007d: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00c2: Expected O, but got Unknown
			if (_fetchedPackage != null && !_isLatestVersion)
			{
				NotificationText message = default(NotificationText);
				((NotificationText)(ref message))..ctor($"There is a new version of {_fetchedPackage.Name}. Go to Thunderstore and download the latest version which is <color=#00FF00>v{_fetchedPackage.Latest.Version}</color>", Color.white, true);
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("Update!"),
					Message = message,
					PopupLength = 5f,
					ShowTitleOnPopup = true,
					Type = (NotificationType)1
				});
			}
		}

		public Package GetPackage(string @namespace, string name, string version = null)
		{
			Package package = SendRequest<Package>($"https://thunderstore.io/api/experimental/package/{@namespace}/{name}/{version ?? string.Empty}");
			if (!IsV1Deprecated && package != null)
			{
				V1PackageMetrics packageMetrics = GetPackageMetrics(@namespace, name);
				if (packageMetrics != null)
				{
					package.TotalDownloads = packageMetrics.Downloads;
					package.RatingScore = packageMetrics.RatingScore;
				}
			}
			return package;
		}

		private static bool IsTaskGood<T>(Task<T> task) where T : class
		{
			if (task != null && task.IsCompletedSuccessfully)
			{
				return task.Result != null;
			}
			return false;
		}

		public T SendRequest<T>(string url)
		{
			Task<HttpResponseMessage> async = new HttpClient(new HttpClientHandler
			{
				ClientCertificateOptions = ClientCertificateOption.Manual,
				ServerCertificateCustomValidationCallback = (HttpRequestMessage _, X509Certificate2? _, X509Chain? _, SslPolicyErrors _) => true
			})
			{
				DefaultRequestHeaders = 
				{
					{ "User-Agent", UserAgent },
					{ "Accept", "application/json" }
				}
			}.GetAsync(url);
			async.Wait();
			HttpResponseMessage httpResponseMessage = async?.Result;
			if (IsTaskGood(async))
			{
				if (!httpResponseMessage.IsSuccessStatusCode)
				{
					HandleHttpError(httpResponseMessage);
					return default(T);
				}
				Task<string> task = httpResponseMessage.Content.ReadAsStringAsync();
				task.Wait();
				string text = task?.Result;
				if (IsTaskGood(task))
				{
					return JsonConvert.DeserializeObject<T>(text);
				}
			}
			return default(T);
		}

		private static void HandleHttpError(HttpResponseMessage result)
		{
			if (IsThunderstoreError(result, out var details))
			{
				if (IsPackageNotFound(result, details))
				{
					throw new ThunderstorePackageNotFoundException("Thunderstore could not find the package");
				}
				throw new ThunderstoreErrorException("Thunderstore API has thrown an unexpected error!", result);
			}
			result.EnsureSuccessStatusCode();
		}

		public V1PackageMetrics GetPackageMetrics(string @namespace, string name)
		{
			if (IsV1Deprecated)
			{
				return null;
			}
			return SendRequest<V1PackageMetrics>($"https://thunderstore.io/api/v1/package-metrics/{@namespace}/{name}/");
		}

		public bool IsLatestVersion(string @namespace, string name, string currentVersion)
		{
			SemVersion currentVersion2 = default(SemVersion);
			if (SemVersion.TryParse(currentVersion, ref currentVersion2, false))
			{
				return IsLatestVersion(@namespace, name, currentVersion2);
			}
			return false;
		}

		public bool IsLatestVersion(string @namespace, string name, Version currentVersion)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			return IsLatestVersion(@namespace, name, new SemVersion(currentVersion));
		}

		public bool IsLatestVersion(string @namespace, string name, SemVersion currentVersion)
		{
			if (!IsV1Deprecated)
			{
				return GetPackageMetrics(@namespace, name)?.IsLatestVersion(currentVersion) ?? false;
			}
			return GetPackage(@namespace, name)?.IsLatestVersion(currentVersion) ?? false;
		}

		private static bool IsPackageNotFound(HttpResponseMessage response, string details = "")
		{
			if (response.StatusCode != HttpStatusCode.NotFound)
			{
				return false;
			}
			if (details != null && details.Length == 0)
			{
				details = GetDetails(response);
			}
			return string.Equals(details, "Not found.", StringComparison.OrdinalIgnoreCase);
		}

		private static bool IsThunderstoreError(HttpResponseMessage response, out string details)
		{
			details = GetDetails(response);
			return !string.IsNullOrWhiteSpace(details);
		}

		private static string GetDetails(HttpResponseMessage response)
		{
			if (response.IsSuccessStatusCode)
			{
				return null;
			}
			Task<string> task = response.Content.ReadAsStringAsync();
			task.Wait();
			string result = task.Result;
			if (string.IsNullOrWhiteSpace(result))
			{
				return null;
			}
			ThunderstoreErrorResponse thunderstoreErrorResponse;
			try
			{
				thunderstoreErrorResponse = JsonConvert.DeserializeObject<ThunderstoreErrorResponse>(result);
			}
			catch (JsonException)
			{
				return null;
			}
			if (!string.IsNullOrWhiteSpace(thunderstoreErrorResponse?.Details))
			{
				return thunderstoreErrorResponse.Details;
			}
			return null;
		}
	}
	public class Package
	{
		[JsonProperty("namespace")]
		public string Namespace { get; internal set; }

		[JsonProperty("name")]
		public string Name { get; internal set; }

		[JsonProperty("full_name")]
		public string FullName { get; internal set; }

		[JsonProperty("owner")]
		public string Owner { get; internal set; }

		[JsonProperty("package_url")]
		public string PackageURL { get; internal set; }

		[JsonProperty("date_created")]
		public DateTime CreatedAt { get; internal set; }

		[JsonProperty("date_updated")]
		public DateTime UpdatedAt { get; internal set; }

		[JsonProperty("rating_score")]
		public int RatingScore { get; internal set; }

		[JsonProperty("is_pinned")]
		public bool IsPinned { get; internal set; }

		[JsonProperty("is_deprecated")]
		public bool IsDeprecated { get; internal set; }

		[JsonProperty("total_downloads")]
		public int TotalDownloads { get; internal set; }

		[JsonProperty("latest")]
		public PackageVersion Latest { get; internal set; }

		[JsonProperty("community_listings")]
		public PackageListing[] CommunityListings { get; internal set; }

		public bool IsLatestVersion(string current)
		{
			if (string.IsNullOrWhiteSpace(current))
			{
				return false;
			}
			if (Latest == null || Latest.SemanticVersion == (SemVersion)null)
			{
				return false;
			}
			SemVersion val = default(SemVersion);
			if (SemVersion.TryParse(current, ref val, false))
			{
				return val >= Latest.SemanticVersion;
			}
			return false;
		}

		public bool IsLatestVersion(SemVersion current)
		{
			if (current == (SemVersion)null)
			{
				return false;
			}
			if (Latest == null || Latest.SemanticVersion == (SemVersion)null)
			{
				return false;
			}
			return current >= Latest.SemanticVersion;
		}

		public bool IsLatestVersion(Version current)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			if (current == null)
			{
				return false;
			}
			if (Latest == null || Latest.SemanticVersion == (SemVersion)null)
			{
				return false;
			}
			return new SemVersion(current) >= Latest.SemanticVersion;
		}
	}
	public class PackageVersion
	{
		[JsonProperty("namespace")]
		public string Namespace { get; internal set; }

		[JsonProperty("name")]
		public string Name { get; internal set; }

		[JsonProperty("version_number")]
		public string Version
		{
			get
			{
				return ((object)SemanticVersion).ToString();
			}
			internal set
			{
				SemanticVersion = SemVersion.Parse(value, false);
			}
		}

		[JsonIgnore]
		public SemVersion SemanticVersion { get; internal set; }

		[JsonProperty("full_name")]
		public string FullName { get; internal set; }

		[JsonProperty("description")]
		public string Description { get; internal set; }

		[JsonProperty("icon")]
		public string Icon { get; internal set; }

		[JsonProperty("dependencies")]
		public List<string> Dependencies { get; internal set; }

		[JsonProperty("download_url")]
		public string DownloadURL { get; internal set; }

		[JsonProperty("date_created")]
		public DateTime CreatedAt { get; internal set; }

		[JsonProperty("downloads")]
		public int Downloads { get; internal set; }

		[JsonProperty("website_url")]
		public string WebsiteURL { get; internal set; }

		[JsonProperty("is_active")]
		public bool IsActive { get; internal set; }
	}
	public class PackageListing
	{
		public enum ReviewStatus
		{
			UNREVIEWED,
			APPROVED,
			REJECTED
		}

		[JsonProperty("has_nsfw_content")]
		public bool HasNSFWContent { get; internal set; }

		[JsonProperty("categories")]
		public List<string> Categories { get; internal set; }

		[JsonProperty("community")]
		public string Community { get; internal set; }

		[JsonProperty("review_status")]
		public string ReviewStatusString
		{
			get
			{
				return ReviewStatusValue.ToString();
			}
			internal set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value");
				}
				if (string.Equals(value, "unreviewed", StringComparison.OrdinalIgnoreCase))
				{
					ReviewStatusValue = ReviewStatus.UNREVIEWED;
				}
				else if (string.Equals(value, "approved", StringComparison.OrdinalIgnoreCase))
				{
					ReviewStatusValue = ReviewStatus.APPROVED;
				}
				else if (string.Equals(value, "rejected", StringComparison.OrdinalIgnoreCase))
				{
					ReviewStatusValue = ReviewStatus.REJECTED;
				}
			}
		}

		[JsonIgnore]
		public ReviewStatus ReviewStatusValue { get; internal set; }
	}
	public class V1PackageMetrics
	{
		[JsonProperty("downloads")]
		public int Downloads { get; internal set; }

		[JsonProperty("rating_score")]
		public int RatingScore { get; internal set; }

		[JsonProperty("latest_version")]
		public string LatestVersion
		{
			get
			{
				return ((object)LatestSemanticVersion).ToString();
			}
			internal set
			{
				LatestSemanticVersion = SemVersion.Parse(value, false);
			}
		}

		[JsonIgnore]
		public SemVersion LatestSemanticVersion { get; internal set; }

		public bool IsLatestVersion(string current)
		{
			if (string.IsNullOrWhiteSpace(current))
			{
				return false;
			}
			if (LatestSemanticVersion == (SemVersion)null)
			{
				return false;
			}
			SemVersion val = default(SemVersion);
			if (SemVersion.TryParse(current, ref val, false))
			{
				return val >= LatestSemanticVersion;
			}
			return false;
		}

		public bool IsLatestVersion(SemVersion current)
		{
			if (current == (SemVersion)null)
			{
				return false;
			}
			if (LatestSemanticVersion == (SemVersion)null)
			{
				return false;
			}
			return current >= LatestSemanticVersion;
		}

		public bool IsLatestVersion(Version current)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (current == null)
			{
				return false;
			}
			if (LatestSemanticVersion == (SemVersion)null)
			{
				return false;
			}
			return new SemVersion(current) >= LatestSemanticVersion;
		}
	}
	public class ThunderstoreErrorResponse
	{
		[JsonProperty("detail")]
		public string Details { get; internal set; }
	}
	public class ThunderstoreErrorException : Exception
	{
		public string Details { get; }

		public HttpStatusCode HttpStatusCode { get; }

		public ThunderstoreErrorException()
		{
		}

		public ThunderstoreErrorException(string message)
			: base(message)
		{
		}

		public ThunderstoreErrorException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public ThunderstoreErrorException(string message, string details, HttpStatusCode httpStatusCode, Exception innerException)
			: base(message, innerException)
		{
			Details = details;
			HttpStatusCode = httpStatusCode;
		}

		public ThunderstoreErrorException(string message, HttpResponseMessage response)
			: base(message)
		{
			if (response.IsSuccessStatusCode)
			{
				return;
			}
			HttpStatusCode = response.StatusCode;
			Task<string> task = response.Content.ReadAsStringAsync();
			task.Wait();
			string result = task.Result;
			if (string.IsNullOrWhiteSpace(result))
			{
				Details = string.Empty;
				return;
			}
			ThunderstoreErrorResponse thunderstoreErrorResponse;
			try
			{
				thunderstoreErrorResponse = JsonConvert.DeserializeObject<ThunderstoreErrorResponse>(result);
			}
			catch (JsonException)
			{
				Details = string.Empty;
				return;
			}
			if (thunderstoreErrorResponse != null)
			{
				Details = thunderstoreErrorResponse.Details;
			}
		}
	}
	public class ThunderstorePackageNotFoundException : ThunderstoreErrorException
	{
		public string Namespace { get; }

		public string Name { get; }

		public string Version { get; }

		public ThunderstorePackageNotFoundException(string message, string @namespace, string name, string details, HttpStatusCode httpStatusCode, Exception innerException)
			: base(message, details, httpStatusCode, innerException)
		{
			Namespace = @namespace;
			Name = name;
		}

		public ThunderstorePackageNotFoundException(string message, string @namespace, string name, string version, string details, HttpStatusCode httpStatusCode, Exception innerException)
			: base(message, details, httpStatusCode, innerException)
		{
			Namespace = @namespace;
			Name = name;
			Version = version;
		}

		public ThunderstorePackageNotFoundException(string message, string @namespace, string name, HttpResponseMessage response)
			: base(message, response)
		{
			Namespace = @namespace;
			Name = name;
		}

		public ThunderstorePackageNotFoundException(string message, string @namespace, string name, string version, HttpResponseMessage response)
			: base(message, response)
		{
			Namespace = @namespace;
			Name = name;
			Version = version;
		}

		public ThunderstorePackageNotFoundException()
		{
		}

		public ThunderstorePackageNotFoundException(string message)
			: base(message)
		{
		}

		public ThunderstorePackageNotFoundException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public ThunderstorePackageNotFoundException(string message, string details, HttpStatusCode httpStatusCode, Exception innerException)
			: base(message, details, httpStatusCode, innerException)
		{
		}

		public ThunderstorePackageNotFoundException(string message, HttpResponseMessage response)
			: base(message, response)
		{
		}
	}
	internal static class TimeUtilities
	{
		private static float _deltaTime = 1f;

		private static float _fixedDeltaTime = 0.02f;

		private static float _timeSinceStartup = 0f;

		private static float _timeScale = 1f;

		private static int _frameCount = 0;

		public static float DeltaTime => _deltaTime;

		public static float FixedDeltaTime => _fixedDeltaTime;

		public static float TimeSinceStartup => _timeSinceStartup;

		public static float TimeScale => _timeScale;

		public static int FrameCount => _frameCount;

		internal static void OnEarlyUpdate()
		{
			_timeScale = Time.timeScale;
			_deltaTime = Time.deltaTime;
			_timeSinceStartup += _deltaTime;
			_frameCount++;
		}

		internal static void OnEarlyFixedUpdate()
		{
			_fixedDeltaTime = Time.fixedDeltaTime;
		}

		public static bool IsMatchingFrame(int interval)
		{
			return FrameCount % interval == 0;
		}

		public static bool IsMatchingFrame(int interval, int offset)
		{
			return (FrameCount + offset) % interval == 0;
		}
	}
}
namespace RandomAvatar.Patches
{
	public static class FusionPatches
	{
		public static void Postfix()
		{
			if (Fusion.IsConnected())
			{
				Core.LevelLoaded();
			}
		}
	}
	public static class LocalRagdollPatches
	{
		public static void Postfix()
		{
			if (RigData.HasPlayer && Core.SwapOnDeath)
			{
				Core.SwapToRandom();
			}
		}
	}
	[HarmonyPatch(typeof(Player_Health))]
	public static class PlayerHealthPatches
	{
		private static long _lastDamage = DateTimeOffset.Now.ToUnixTimeMilliseconds();

		private const int _damageDelay = 250;

		[HarmonyPatch("Death")]
		[HarmonyPostfix]
		public static void Postfix(Player_Health __instance)
		{
			if (Fusion.IsMine((Component)(object)__instance) && Core.SwapOnDeath)
			{
				PlayerHealthDecorator val = default(PlayerHealthDecorator);
				if (Core.Entry_EffectWhenSwitching.Value && (Object)(object)PlayerMarkerPatches.Instance != (Object)null && (!((Component)PlayerMarkerPatches.Instance).TryGetComponent<PlayerHealthDecorator>(ref val) || !val._reloadLevelOnDeath))
				{
					Core.SwapOnNextLevelChange = true;
				}
				Core.SwapToRandom();
			}
		}

		[HarmonyPatch("TAKEDAMAGE")]
		[HarmonyPostfix]
		public static void Postfix2(Player_Health __instance)
		{
			if (Fusion.IsMine((Component)(object)__instance) && Core.SwapOnDamaged)
			{
				if (DateTimeOffset.Now.ToUnixTimeMilliseconds() - _lastDamage >= 250)
				{
					Core.SwapToRandom();
				}
				_lastDamage = DateTimeOffset.Now.ToUnixTimeMilliseconds();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMarker))]
	public static class PlayerMarkerPatches
	{
		public static PlayerMarker Instance { get; private set; }

		[HarmonyPatch("Awake")]
		public static void Postfix(PlayerMarker __instance)
		{
			Instance = __instance;
		}
	}
}
namespace RandomAvatar.Menu
{
	public static class BoneMenu
	{
		private static float elapsed = 0f;

		private static IntElement DelayElement;

		internal const int _rmd = 5;

		internal static bool IsSetup = false;

		internal static Action EverySecond;

		internal static int Cooldown = 0;

		internal static FunctionElement IsAllowedLabel;

		internal static FunctionElement FusionDelayLabel;

		private static float _generalElapsed;

		private static float _lastDelay;

		private static int _lastMinimumDelay;

		public static Page AuthorPage { get; private set; }

		public static Page ModPage { get; private set; }

		public static Page SettingsPage { get; private set; }

		public static Page RepeatingPage { get; private set; }

		public static Page ChallengesPage { get; private set; }

		public static Page FusionPage { get; private set; }

		public static Page HistoryPage { get; private set; }

		public static Page AvatarHistoryPage { get; private set; }

		public static Page AvatarHistoryTagsPage { get; private set; }

		public static Page BlacklistWhitelistPage { get; private set; }

		internal static FunctionElement RemainingLabel { get; private set; }

		public static int Delay { get; private set; } = 30;


		public static int Remaining { get; private set; } = 0;


		public static bool SwitchEvery { get; private set; } = false;


		public static bool SwapOnStart { get; private set; } = true;


		public static int MinimumDelay => Fusion.GetMinimumDelay();

		private static int RepeatingMinimumDelay
		{
			get
			{
				int num = Fusion.GetMinimumDelay();
				if (num < 5)
				{
					num = 5;
				}
				return num;
			}
		}

		internal static FunctionElement CooldownLabel { get; private set; }

		internal static void AssetWarehouseReady()
		{
			BlacklistWhitelist.SetupPage();
			Hooking.OnWarehouseReady -= AssetWarehouseReady;
		}

		internal static void Setup()
		{
			//IL_0018: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: 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_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			if (IsSetup)
			{
				return;
			}
			IsSetup = true;
			AuthorPage = Page.Root.CreatePage("HAHOOS", Color.white, 0, true);
			ModPage = AuthorPage.CreatePage("RandomAvatar", Color.magenta, 0, true);
			SettingsPage = ModPage.CreatePage("Settings", Color.cyan, 4, true);
			SettingsPage.CreateBoolPref("Use Redacted Avatars", Color.cyan, ref Core.Entry_UseRedacted);
			SettingsPage.CreateBoolPref("Add effect when switching avatar", Color.magenta, ref Core.Entry_EffectWhenSwitching);
			BlacklistWhitelistPage = ModPage.CreatePage("Blacklist/Whitelist", Color.magenta, 10, true);
			BlacklistWhitelist.Page = BlacklistWhitelistPage;
			if (!AssetWarehouse.ready)
			{
				Hooking.OnWarehouseReady += AssetWarehouseReady;
			}
			else
			{
				BlacklistWhitelist.SetupPage();
			}
			_lastMinimumDelay = MinimumDelay;
			HistoryPage = ModPage.CreatePage("History", Color.yellow, 10, true);
			AvatarHistoryPage = HistoryPage.CreatePage("Placeholder", Color.white, 0, false);
			AvatarHistoryTagsPage = AvatarHistoryPage.CreatePage("Tags", Color.red, 0, false);
			SetupHistoryPage();
			RepeatingPage = ModPage.CreatePage("Repeating", Color.red, 4, true);
			UpdateRepeating();
			ChallengesPage = ModPage.CreatePage("Challenges", Color.yellow, 3, true);
			ChallengesPage.CreateBool("Switch to random avatar on death", Color.cyan, false, (Action<bool>)delegate(bool v)
			{
				Core.SwapOnDeath = v;
			});
			ChallengesPage.CreateBool("Switch to random avatar on level change", Color.yellow, false, (Action<bool>)delegate(bool v)
			{
				Core.SwapOnLevelChange = v;
			});
			ChallengesPage.CreateBool("Switch to random avatar on damaged", Color.magenta, false, (Action<bool>)delegate(bool v)
			{
				Core.SwapOnDamaged = v;
			});
			if (HelperMethods.CheckIfAssemblyLoaded("labfusion"))
			{
				FusionPage = ModPage.CreatePage("Fusion", Color.cyan, 0, true);
				SetupFusionPage();
				Fusion.ServerChanged = (Action)Delegate.Combine(Fusion.ServerChanged, (Action)delegate
				{
					SetupFusionPage();
					Cooldown = 0;
				});
				EverySecond = (Action)Delegate.Combine(EverySecond, new Action(UpdateLabels));
				EverySecond = (Action)Delegate.Combine(EverySecond, new Action(Fusion.EnsureSync));
			}
			EverySecond = (Action)Delegate.Combine(EverySecond, new Action(CheckDelay));
			ModPage.CreateFunction("Switch to random avatar", Color.white, (Action)Core.SwapToRandom);
			if (HelperMethods.CheckIfAssemblyLoaded("labfusion"))
			{
				CooldownLabel = ModPage.CreateLabel(((Cooldown > 0) ? $"Cooldown: {Cooldown}" : "Ready to use") ?? "", Color.white);
			}
			Core.Thunderstore.BL_CreateMenuLabel(ModPage, createBlankSpace: false);
		}

		internal static void SetupTagsPage(AvatarCrate crate)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			BlacklistWhitelist.TagsHandler.SetupPage();
			BlacklistWhitelist.CleanupPage(AvatarHistoryTagsPage);
			if (((Crate)crate).Tags.Count <= 0)
			{
				AvatarHistoryTagsPage.CreateLabel("Nothing to show here :(", Color.white);
				return;
			}
			Dictionary<string, int> tags = new Dictionary<string, int>();
			((Crate)crate).Tags.ForEach(Action<string>.op_Implicit((Action<string>)delegate(string x)
			{
				if (!string.IsNullOrWhiteSpace(x))
				{
					int value = BlacklistWhitelist.GetAllTags().FirstOrDefault((AvatarTag y) => y.Tag == x)?.Count ?? 0;
					tags.Add(x, value);
				}
			}));
			tags = tags.OrderByDescending((KeyValuePair<string, int> x) => x.Value).ToDictionary((KeyValuePair<string, int> x) => x.Key, (KeyValuePair<string, int> x) => x.Value);
			tags.ForEach(delegate(KeyValuePair<string, int> x)
			{
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				FunctionElement element = null;
				element = AvatarHistoryTagsPage.CreateFunction($"{x.Key} [{x.Value}]", (Color)(BlacklistWhitelist.TagsHandler.List.Value.Contains(x.Key) ? new Color(0f, 1f, 0f) : Color.red), (Action)delegate
				{
					//IL_0087: Unknown result type (might be due to invalid IL or missing references)
					//IL_0047: Unknown result type (might be due to invalid IL or missing references)
					if (BlacklistWhitelist.TagsHandler.List.Value.Contains(x.Key))
					{
						BlacklistWhitelist.TagsHandler.List.Value.Remove(x.Key);
						((Element)element).ElementColor = Color.red;
					}
					else
					{
						BlacklistWhitelist.TagsHandler.List.Value.Add(x.Key);
						((Element)element).ElementColor = new Color(0f, 1f, 0f);
					}
					BlacklistWhitelist.Category.SaveToFile(false);
				});
			});
		}

		internal static void SetupPageForAvatar(DateTimeOffset offset, AvatarCrate crate)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			BlacklistWhitelist.PalletHandler.SetupPage();
			AvatarHistoryPage.Name = ((Scannable)crate).Title;
			AvatarHistoryPage.RemoveAll();
			AvatarHistoryPage.CreateFunction(((Scannable)crate).Title, Color.white, (Action)null);
			AvatarHistoryPage.CreateFunction(((Scannable)crate).Barcode.ID, Color.white, (Action)null);
			AvatarHistoryPage.CreateFunction("Change into avatar", Color.cyan, (Action)delegate
			{
				Core.SwapAvatar(((Scannable)crate).Barcode.ID, Core.Entry_EffectWhenSwitching.Value);
			});
			FunctionElement palletElement = null;
			palletElement = AvatarHistoryPage.CreateFunction(((Scannable)((Crate)crate).Pallet).Title + " [" + (BlacklistWhitelist.GetAllPallets().FirstOrDefault((PalletRef x) => ((Scannable)x.Pallet).Barcode == ((Scannable)((Crate)crate).Pallet).Barcode).Avatars.Count.ToString() ?? "0") + "]", (Color)(BlacklistWhitelist.PalletHandler.List.Value.Contains(((Scannable)((Crate)crate).Pallet).Barcode.ID) ? new Color(0f, 1f, 0f) : Color.red), (Action)delegate
			{
				//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				if (BlacklistWhitelist.PalletHandler.List.Value.Contains(((Scannable)((Crate)crate).Pallet).Barcode.ID))
				{
					BlacklistWhitelist.PalletHandler.List.Value.Remove(((Scannable)((Crate)crate).Pallet).Barcode.ID);
					((Element)palletElement).ElementColor = Color.red;
				}
				else
				{
					BlacklistWhitelist.PalletHandler.List.Value.Add(((Scannable)((Crate)crate).Pallet).Barcode.ID);
					((Element)palletElement).ElementColor = new Color(0f, 1f, 0f);
				}
				BlacklistWhitelist.Category.SaveToFile(false);
			});
			AvatarHistoryPage.CreateFunction($"Tags ({((Crate)crate).Tags.Count})", Color.red, (Action)delegate
			{
				SetupTagsPage(crate);
				Menu.OpenPage(AvatarHistoryTagsPage);
			});
			AvatarHistoryPage.CreateFunction($"Time: {offset:T}", Color.white, (Action)null);
			FunctionElement element = null;
			element = AvatarHistoryPage.CreateFunction((!BlacklistWhitelist.AvatarHandler.List.Value.Contains(((Scannable)crate).Barcode.ID)) ? (BlacklistWhitelist.IsWhitelist.Value ? "Not Whitelisted" : "Not Blacklisted") : (BlacklistWhitelist.IsWhitelist.Value ? "Whitelisted" : "Blacklisted"), (Color)(BlacklistWhitelist.AvatarHandler.List.Value.Contains(((Scannable)crate).Barcode.ID) ? new Color(0f, 1f, 0f) : Color.red), (Action)delegate
			{
				//IL_00dc: 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)
				if (BlacklistWhitelist.AvatarHandler.List.Value.Contains(((Scannable)crate).Barcode.ID))
				{
					BlacklistWhitelist.AvatarHandler.List.Value.Remove(((Scannable)crate).Barcode.ID);
					((Element)element).ElementName = (BlacklistWhitelist.IsWhitelist.Value ? "Not Whitelisted" : "Not Blacklisted");
					((Element)element).ElementColor = Color.red;
				}
				else
				{
					BlacklistWhitelist.AvatarHandler.List.Value.Add(((Scannable)crate).Barcode.ID);
					((Element)element).ElementName = (BlacklistWhitelist.IsWhitelist.Value ? "Whitelisted" : "Blacklisted");
					((Element)element).ElementColor = new Color(0f, 1f, 0f);
				}
				BlacklistWhitelist.Category.SaveToFile(false);
			});
		}

		internal static void SetupHistoryPage()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (HistoryPage == null)
			{
				return;
			}
			BlacklistWhitelist.CleanupPage(HistoryPage);
			((Element)HistoryPage.CreateFunction("Clear all", Color.red, (Action)delegate
			{
				Core.AvatarHistory.Clear();
				SetupHistoryPage();
			})).SetProperty((ElementProperties)1);
			HistoryPage.CreateBlank();
			if (Core.AvatarHistory.Count == 0)
			{
				HistoryPage.CreateLabel("Nothing to show here :(", Color.white);
				return;
			}
			Core.AvatarHistory = Core.AvatarHistory.OrderByDescending((KeyValuePair<DateTimeOffset, AvatarCrate> x) => x.Key.ToUnixTimeMilliseconds()).ToDictionary((KeyValuePair<DateTimeOffset, AvatarCrate> x) => x.Key, (KeyValuePair<DateTimeOffset, AvatarCrate> x) => x.Value);
			Core.AvatarHistory.ForEach(delegate(KeyValuePair<DateTimeOffset, AvatarCrate> y)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				AvatarCrate x2 = y.Value;
				((Element)HistoryPage.CreateFunction(((Scannable)x2).Title, Color.yellow, (Action)delegate
				{
					SetupPageForAvatar(y.Key, x2);
					Menu.OpenPage(AvatarHistoryPage);
				})).SetProperty((ElementProperties)1);
			});
		}

		internal static void UpdateRepeating()
		{
			//IL_0022: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			if (RepeatingPage == null)
			{
				return;
			}
			RepeatingPage.RemoveAll();
			DelayElement = RepeatingPage.CreateInt("Change Delay", Color.yellow, Delay, 5, RepeatingMinimumDelay, 3600, (Action<int>)delegate(int v)
			{
				Delay = v;
			});
			RepeatingPage.CreateBool("Swap on start", Color.red, SwapOnStart, (Action<bool>)delegate(bool v)
			{
				SwapOnStart = v;
			});
			ToggleFunctionElement _switchEvery = RepeatingPage.CreateToggleFunction("Switch to random avatar every set seconds", Color.white, null);
			_switchEvery.Started += delegate
			{
				if (!SwitchEvery)
				{
					if (Delay < RepeatingMinimumDelay)
					{
						Core.Logger.Error("Cannot use repeated avatar change, set delay is below minimum");
						_switchEvery.Cancel();
					}
					else
					{
						Remaining = Delay;
						_lastDelay = Delay;
						SwitchEvery = true;
						if (SwapOnStart)
						{
							Core.SwapToRandom();
						}
					}
				}
			};
			_switchEvery.Cancelled += delegate
			{
				SwitchEvery = false;
			};
			if (SwitchEvery)
			{
				_switchEvery.Start();
			}
			FunctionElement obj = RepeatingPage.CreateFunction("Time until switch: N/A", Color.white, (Action)null);
			((Element)obj).SetProperty((ElementProperties)1);
			RemainingLabel = obj;
		}

		internal static void UpdateLabels()
		{
			if (IsAllowedLabel != null)
			{
				if (Fusion.IsConnected())
				{
					((Element)IsAllowedLabel).ElementName = "Is currently allowed: " + (Fusion.IsAllowed() ? "<color=#2EFF2E>Yes</color>" : "<color=#FF0000>No</color>");
					((Element)FusionDelayLabel).ElementName = $"Minimum Delay: <color=#00FFFF>{MinimumDelay}{((MinimumDelay != RepeatingMinimumDelay) ? $" (Repeated {RepeatingMinimumDelay})" : "")}</color>";
				}
				else
				{
					((Element)IsAllowedLabel).ElementName = string.Empty;
					((Element)FusionDelayLabel).ElementName = string.Empty;
				}
			}
		}

		internal static void CheckDelay()
		{
			if (DelayElement != null && Delay < RepeatingMinimumDelay)
			{
				Delay = RepeatingMinimumDelay;
				DelayElement.Value = Delay;
			}
		}

		internal static void SetupFusionPage()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			if (FusionPage != null && IsSetup)
			{
				FusionPage.RemoveAll();
				FusionPage.CreateBoolPref("Allow Random Avatar", Color.cyan, ref Core.Entry_AllowRandomAvatarInYourLobbies, null, delegate
				{
					Fusion.UpdateMetadata();
				});
				FusionPage.CreateIntPref("Delay/Cooldown", Color.yellow, ref Core.Entry_MinimumFusionDelay, 5, 0, 3600, null, delegate
				{
					Fusion.UpdateMetadata();
				});
				Fusion.UpdateMetadata();
				IsAllowedLabel = FusionPage.CreateLabel("Is currently allowed: " + (Fusion.IsAllowed() ? "<color=#2EFF2E>Yes</color>" : "<color=#FF0000>No</color>"), Color.white);
				FusionDelayLabel = FusionPage.CreateLabel($"Minimum Delay/Cooldown: <color=#00FFFF>{MinimumDelay}{((MinimumDelay != RepeatingMinimumDelay) ? $" (Repeated {RepeatingMinimumDelay})" : "")}</color>", Color.white);
			}
		}

		internal static void Update()
		{
			if (_lastMinimumDelay != RepeatingMinimumDelay)
			{
				UpdateRepeating();
				_lastMinimumDelay = RepeatingMinimumDelay;
			}
			_generalElapsed += TimeUtilities.DeltaTime;
			if (_generalElapsed >= 1f)
			{
				_generalElapsed = 0f;
				if (CooldownLabel != null)
				{
					if (Fusion.IsConnected() && Cooldown > 0)
					{
						Cooldown--;
					}
					else if (!Fusion.IsConnected())
					{
						Cooldown = 0;
					}
					if (Fusion.IsConnected())
					{
						((Element)CooldownLabel).ElementName = ((Cooldown > 0) ? $"Cooldown: {Cooldown}" : "Ready to use") ?? "";
					}
					else
					{
						((Element)CooldownLabel).ElementName = string.Empty;
					}
				}
				EverySecond?.Invoke();
			}
			if (RemainingLabel == null)
			{
				return;
			}
			if (SwitchEvery)
			{
				if (Fusion.IsAllowed())
				{
					if (_lastDelay == (float)Delay)
					{
						elapsed += TimeUtilities.DeltaTime;
						if (elapsed >= 1f)
						{
							Remaining--;
							elapsed = 0f;
						}
						if (Remaining <= 0)
						{
							Core.SwapToRandom();
							Remaining = Delay;
						}
					}
					else
					{
						_lastDelay = Delay;
						Remaining = Delay;
						elapsed = 0f;
					}
				}
				else
				{
					_lastDelay = 0f;
					Remaining = 0;
					elapsed = 0f;
					SwitchEvery = false;
				}
				if (!((Element)RemainingLabel).ElementName.EndsWith(Remaining.ToString()))
				{
					((Element)RemainingLabel).ElementName = $"Time until switch: {Remaining}";
				}
			}
			else if (!((Element)RemainingLabel).ElementName.EndsWith("N/A"))
			{
				((Element)RemainingLabel).ElementName = "Time until switch: N/A";
			}
		}
	}
}
namespace RandomAvatar.Menu.Elements
{
	public class BlankElement
	{
		public readonly FunctionElement Element;

		public BlankElement()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Element = new FunctionElement(string.Empty, Color.white, (Action)null);
			((Element)Element).SetProperty((ElementProperties)1);
		}
	}
	public class ToggleFunctionElement
	{
		public readonly FunctionElement Element;

		public Action<ToggleFunctionElement> Callback;

		public Color OffColor;

		public Color OnColor;

		public bool IsRunning { get; private set; }

		public event Action Started;

		public event Action Cancelled;

		public void Start()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!IsRunning)
			{
				IsRunning = true;
				((Element)Element).ElementColor = OnColor;
				this.Started?.Invoke();
				Callback?.Invoke(this);
			}
		}

		public void Cancel()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (IsRunning)
			{
				IsRunning = false;
				((Element)Element).ElementColor = OffColor;
				this.Cancelled?.Invoke();
			}
		}

		public ToggleFunctionElement(string name, Color offColor, Color onColor, Action<ToggleFunctionElement> callback)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Callback = callback;
			OffColor = offColor;
			OnColor = onColor;
			Element = new FunctionElement(name, offColor, (Action)delegate
			{
				if (IsRunning)
				{
					Cancel();
				}
				else
				{
					Start();
				}
			});
		}

		public ToggleFunctionElement(string name, Color offColor, Action<ToggleFunctionElement> callback)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			Callback = callback;
			OffColor = offColor;
			OnColor = Color.red;
			Element = new FunctionElement(name, offColor, (Action)delegate
			{
				if (IsRunning)
				{
					Cancel();
				}
				else
				{
					Start();
				}
			});
		}
	}
}
namespace RandomAvatar.Helper
{
	internal static class BLHelper
	{
		private static readonly MelonPreferences_Category prefs = Core.Preferences_Category;

		internal static IntElement CreateIntPref(this Page page, string name, Color color, ref MelonPreferences_Entry<int> value, int increment, int minValue, int maxValue, MelonPreferences_Category category = null, Action<int> callback = null, string prefName = null, int prefDefaultValue = 0)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (category == null)
			{
				category = prefs;
			}
			if (value == null || !category.HasEntry(((MelonPreferences_Entry)value).Identifier))
			{
				if (prefName == null)
				{
					prefName = name;
				}
				if (!category.HasEntry(prefName))
				{
					value = category.CreateEntry<int>(prefName, prefDefaultValue, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
				}
			}
			MelonPreferences_Entry<int> val = value;
			IntElement val2 = page.CreateInt(name, color, val.Value, increment, minValue, maxValue, (Action<int>)delegate(int x)
			{
				val.Value = x;
				category.SaveToFile(false);
				Action<int> action = callback;
				if (action != null)
				{
					Extensions.InvokeActionSafe<int>(action, x);
				}
			});
			if (!string.IsNullOrWhiteSpace(((MelonPreferences_Entry)value).Description))
			{
				((Element)val2).SetTooltip(((MelonPreferences_Entry)value).Description);
			}
			return val2;
		}

		internal static FloatElement CreateFloatPref(this Page page, string name, Color color, ref MelonPreferences_Entry<float> value, float increment, float minValue, float maxValue, MelonPreferences_Category category = null, Action<float> callback = null, string prefName = null, float prefDefaultValue = 0f)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (category == null)
			{
				category = prefs;
			}
			if (value == null || !category.HasEntry(((MelonPreferences_Entry)value).Identifier))
			{
				if (prefName == null)
				{
					prefName = name;
				}
				if (!category.HasEntry(prefName))
				{
					value = category.CreateEntry<float>(prefName, prefDefaultValue, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
				}
			}
			MelonPreferences_Entry<float> val = value;
			FloatElement val2 = page.CreateFloat(name, color, val.Value, increment, minValue, maxValue, (Action<float>)delegate(float x)
			{
				val.Value = x;
				category.SaveToFile(false);
				Action<float> action = callback;
				if (action != null)
				{
					Extensions.InvokeActionSafe<float>(action, x);
				}
			});
			if (!string.IsNullOrWhiteSpace(((MelonPreferences_Entry)value).Description))
			{
				((Element)val2).SetTooltip(((MelonPreferences_Entry)value).Description);
			}
			return val2;
		}

		internal static BoolElement CreateBoolPref(this Page page, string name, Color color, ref MelonPreferences_Entry<bool> value, MelonPreferences_Category category = null, Action<bool> callback = null, string prefName = null, bool prefDefaultValue = false)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (category == null)
			{
				category = prefs;
			}
			if (value == null || !category.HasEntry(((MelonPreferences_Entry)value).Identifier))
			{
				if (prefName == null)
				{
					prefName = name;
				}
				if (!category.HasEntry(prefName))
				{
					value = category.CreateEntry<bool>(prefName, prefDefaultValue, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
				}
			}
			MelonPreferences_Entry<bool> val = value;
			BoolElement val2 = page.CreateBool(name, color, val.Value, (Action<bool>)delegate(bool x)
			{
				val.Value = x;
				category.SaveToFile(false);
				Action<bool> action = callback;
				if (action != null)
				{
					Extensions.InvokeActionSafe<bool>(action, x);
				}
			});
			if (!string.IsNullOrWhiteSpace(((MelonPreferences_Entry)value).Description))
			{
				((Element)val2).SetTooltip(((MelonPreferences_Entry)value).Description);
			}
			return val2;
		}

		internal static EnumElement CreateEnumPref<T>(this Page page, string name, Color color, ref MelonPreferences_Entry<T> value, MelonPreferences_Category category = null, Action<Enum> callback = null, string prefName = null, Enum prefDefaultValue = null) where T : Enum
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if (category == null)
			{
				category = prefs;
			}
			if (value == null || !category.HasEntry(((MelonPreferences_Entry)value).Identifier))
			{
				if (prefName == null)
				{
					prefName = name;
				}
				if (!category.HasEntry(prefName))
				{
					value = category.CreateEntry<T>(prefName, (T)prefDefaultValue, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
				}
			}
			MelonPreferences_Entry<T> val = value;
			EnumElement val2 = page.CreateEnum(name, color, (Enum)val.Value, (Action<Enum>)delegate(Enum x)
			{
				val.Value = (T)x;
				category.SaveToFile(false);
				Action<Enum> action = callback;
				if (action != null)
				{
					Extensions.InvokeActionSafe<Enum>(action, x);
				}
			});
			if (!string.IsNullOrWhiteSpace(((MelonPreferences_Entry)value).Description))
			{
				((Element)val2).SetTooltip(((MelonPreferences_Entry)value).Description);
			}
			return val2;
		}

		internal static StringElement CreateStringPref(this Page page, string name, Color color, ref MelonPreferences_Entry<string> value, MelonPreferences_Category category = null, Action<string> callback = null, string prefName = null, string prefDefaultValue = null)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (category == null)
			{
				category = prefs;
			}
			if (value == null || !category.HasEntry(((MelonPreferences_Entry)value).Identifier))
			{
				if (prefName == null)
				{
					prefName = name;
				}
				if (!category.HasEntry(prefName))
				{
					value = category.CreateEntry<string>(prefName, prefDefaultValue, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
				}
			}
			MelonPreferences_Entry<string> val = value;
			StringElement val2 = page.CreateString(name, color, val.Value, (Action<string>)delegate(string x)
			{
				val.Value = x;
				category.SaveToFile(false);
				Action<string> action = callback;
				if (action != null)
				{
					Extensions.InvokeActionSafe<string>(action, x);
				}
			});
			val2.Value = value.Value;
			if (!string.IsNullOrWhiteSpace(((MelonPreferences_Entry)value).Description))
			{
				((Element)val2).SetTooltip(((MelonPreferences_Entry)value).Description);
			}
			return val2;
		}

		public static FunctionElement CreateLabel(this Page page, string text, Color color)
		{
			//IL_0001: 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_0009: Expected O, but got Unknown
			FunctionElement val = new FunctionElement(text, color, (Action)null);
			((Element)val).SetProperty((ElementProperties)1);
			page.Add((Element)(object)val);
			return val;
		}

		public static ToggleFunctionElement CreateToggleFunction(this Page page, string name, Color offColor, Color onColor, Action<ToggleFunctionElement> callback)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ToggleFunctionElement toggleFunctionElement = new ToggleFunctionElement(name, offColor, onColor, callback);
			page.Add((Element)(object)toggleFunctionElement.Element);
			return toggleFunctionElement;
		}

		public static ToggleFunctionElement CreateToggleFunction(this Page page, string name, Color offColor, Action<ToggleFunctionElement> callback)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ToggleFunctionElement toggleFunctionElement = new ToggleFunctionElement(name, offColor, callback);
			page.Add((Element)(object)toggleFunctionElement.Element);
			return toggleFunctionElement;
		}

		public static BlankElement CreateBlank(this Page page)
		{
			BlankElement blankElement = new BlankElement();
			page.Add((Element)(object)blankElement.Element);
			return blankElement;
		}

		internal static void SendNotification(string title, string message, bool showTitleOnPopup = false, float popupLength = 2f, NotificationType type = 0, Texture2D customIcon = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//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_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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			Notifier.Send(new Notification
			{
				Title = new NotificationText("RandomAvatar | " + title, Color.white, true),
				Message = new NotificationText(message, Color.white, true),
				ShowTitleOnPopup = showTitleOnPopup,
				CustomIcon = customIcon,
				PopupLength = popupLength,
				Type = type
			});
		}

		internal static void SendNotification(NotificationText title, NotificationText message, bool showTitleOnPopup = false, float popupLength = 2f, NotificationType type = 0, Texture2D customIcon = null)
		{
			//IL_0007: 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_001c: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			title.Text = "RandomAvatar | " + title.Text;
			Notifier.Send(new Notification
			{
				Title = title,
				Message = message,
				ShowTitleOnPopup = showTitleOnPopup,
				CustomIcon = customIcon,
				PopupLength = popupLength,
				Type = type
			});
		}

		internal static void SendNotification(Notification notification)
		{
			Notifier.Send(notification);
		}
	}
	public static class OtherHelpers
	{
		public static void ForEach<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, Action<KeyValuePair<TKey, TValue>> action)
		{
			foreach (KeyValuePair<TKey, TValue> item in dictionary)
			{
				action?.Invoke(item);
			}
		}

		public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
		{
			foreach (T item in enumerable)
			{
				action?.Invoke(item);
			}
		}
	}
}