Decompiled source of ResourcefulHands v0.10.0

plugins/monksilly.ResourcefulHands.dll

Decompiled 2 days ago
#define DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using ResourcefulHands.Patches;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("monksilly.ResourcefulHands")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.10.0.0")]
[assembly: AssemblyInformationalVersion("0.10.0+55f35e087afd227e5ca96c36c7a64cc83bda3181")]
[assembly: AssemblyProduct("Resourceful Hands")]
[assembly: AssemblyTitle("monksilly.ResourcefulHands")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.10.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ResourcefulHands
{
	public static class MiscUtils
	{
		public static string CleanString(string str)
		{
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			char[] array = invalidFileNameChars;
			foreach (char c in array)
			{
				str = str.Replace(c.ToString(), "");
			}
			StringBuilder stringBuilder = new StringBuilder();
			string text = str;
			foreach (char c2 in text)
			{
				if (c2 <= '\u007f')
				{
					stringBuilder.Append(c2);
				}
			}
			return stringBuilder.ToString();
		}

		public static void WriteString(this Stream stream, string value)
		{
			foreach (char c in value)
			{
				stream.WriteByte((byte)c);
			}
		}

		public static void WriteInteger(this Stream stream, uint value)
		{
			stream.WriteByte((byte)(value & 0xFFu));
			stream.WriteByte((byte)((value >> 8) & 0xFFu));
			stream.WriteByte((byte)((value >> 16) & 0xFFu));
			stream.WriteByte((byte)((value >> 24) & 0xFFu));
		}

		public static void WriteShort(this Stream stream, ushort value)
		{
			stream.WriteByte((byte)(value & 0xFFu));
			stream.WriteByte((byte)((uint)(value >> 8) & 0xFFu));
		}

		public static RenderTexture ConvertToARGB32(this RenderTexture self)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)self.format == 0)
			{
				return self;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)self).width, ((Texture)self).height, 0, (RenderTextureFormat)0);
			Graphics.Blit((Texture)(object)self, temporary);
			return temporary;
		}

		public static AudioClip CreateAudioClip(float[] samples, int sampleRate, int channels, string name = "GeneratedClip")
		{
			int num = samples.Length / channels;
			AudioClip val = AudioClip.Create(name, num, channels, sampleRate, true);
			val.SetData(samples, 0);
			return val;
		}

		public static string GetSHA256Checksum(string filePath)
		{
			using FileStream inputStream = File.OpenRead(filePath);
			using SHA256 sHA = SHA256.Create();
			byte[] array = sHA.ComputeHash(inputStream);
			StringBuilder stringBuilder = new StringBuilder();
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("x2"));
			}
			return stringBuilder.ToString();
		}

		public static Transform? FindParentWithName(Transform current, string name)
		{
			while (((Object)current).name != name)
			{
				current = current.parent;
				if ((Object)(object)current == (Object)null)
				{
					return null;
				}
			}
			return current;
		}

		public static Transform? FindChildWithParentNamed(Transform current, string name)
		{
			while (((Object)current.parent).name != name)
			{
				current = current.parent;
				if ((Object)(object)current == (Object)null)
				{
					return null;
				}
				if ((Object)(object)current.parent == (Object)null)
				{
					return null;
				}
			}
			return current;
		}

		public static Transform? FindTopmostParent(Transform current)
		{
			while ((Object)(object)current.parent != (Object)null)
			{
				current = current.parent;
				if ((Object)(object)current == (Object)null)
				{
					return null;
				}
			}
			return current;
		}

		public static T? FindAt<T>(this Transform t, string path) where T : Component
		{
			string[] array = path.Split('/');
			foreach (string text in array)
			{
				t = t.Find(text);
				if ((Object)(object)t == (Object)null)
				{
					return default(T);
				}
			}
			return ((Component)t).GetComponentInChildren<T>();
		}
	}
	[BepInPlugin("monksilly.resourcefulhands", "Resourceful Hands", "0.9.70")]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass31_1
		{
			private sealed class <<Awake>g__PollSpriteRenderers|6>d : IEnumerator<object>, IEnumerator, IDisposable
			{
				private int <>1__state;

				private object <>2__current;

				public <>c__DisplayClass31_1 <>4__this;

				object? IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object? IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <<Awake>g__PollSpriteRenderers|6>d(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_004a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0054: Expected O, but got Unknown
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						break;
					case 1:
						<>1__state = -1;
						break;
					}
					<>4__this.spriteRenderers = Object.FindObjectsByType<SpriteRenderer>((FindObjectsSortMode)0);
					<>4__this.lastTick = Time.time;
					<>2__current = (object)new WaitForSeconds(1f / 60f);
					<>1__state = 1;
					return true;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			public Coroutine c;

			public SpriteRenderer[] spriteRenderers;

			public float lastTick;

			internal void <Awake>b__5()
			{
				if (Time.time - lastTick > 8f / 15f)
				{
					RHLog.Warning("Sprite finder thread has been dead for a while, restarting...", 210, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					CreateCoroutine();
				}
				SpriteRenderer[] array = spriteRenderers;
				foreach (SpriteRenderer sr in array)
				{
					SpriteRendererPatches.Patch(sr);
				}
				void CreateCoroutine()
				{
					if (c != null)
					{
						CoroutineDispatcher.StopDispatch(c);
					}
					c = CoroutineDispatcher.Dispatch(PollSpriteRenderers());
				}
				[IteratorStateMachine(typeof(<<Awake>g__PollSpriteRenderers|6>d))]
				IEnumerator PollSpriteRenderers()
				{
					//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
					return new <<Awake>g__PollSpriteRenderers|6>d(0)
					{
						<>4__this = this
					};
				}
			}
		}

		public const string GUID = "monksilly.resourcefulhands";

		public GameObject? ofHolder;

		private static AssetBundle? _assets;

		public static Texture2D? CorruptionTexture;

		public static Texture2D? Icon;

		public static Texture2D? IconGray;

		internal static int targetFps = 60;

		private static int _mainThreadId;

		public static AssetBundle? Assets
		{
			get
			{
				if (Object.op_Implicit((Object)(object)_assets))
				{
					return _assets;
				}
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				using Stream stream = executingAssembly.GetManifestResourceStream("ResourcefulHands.rh_assets.bundle");
				if (stream != null)
				{
					_assets = AssetBundle.LoadFromStream(stream);
				}
				AssetBundle? assets = _assets;
				CorruptionTexture = ((assets != null) ? assets.LoadAsset<Texture2D>("Corruption1") : null);
				AssetBundle? assets2 = _assets;
				Icon = ((assets2 != null) ? assets2.LoadAsset<Texture2D>("icon") : null);
				AssetBundle? assets3 = _assets;
				IconGray = ((assets3 != null) ? assets3.LoadAsset<Texture2D>("gray_icon") : null);
				return _assets;
			}
			private set
			{
				_assets = value;
			}
		}

		public static Plugin Instance { get; private set; } = null;


		internal static ManualLogSource Log { get; private set; } = null;


		public static bool IsDemo
		{
			get
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: 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)
				try
				{
					AppId appId = SteamClient.AppId;
					RHLog.Debug($"Appid: {appId}", 65, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					if (appId.Value == 3218540)
					{
						return true;
					}
				}
				catch (Exception data)
				{
					RHLog.Error(data, 68, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
				}
				return false;
			}
		}

		private Harmony? Harmony { get; set; }

		public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

		public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == _mainThreadId;

		private static void RefreshTextures()
		{
			RHSpriteManager.ClearSpriteCache();
			List<Material> allMaterials = Object.FindObjectsByType<Material>((FindObjectsInactive)1, (FindObjectsSortMode)0).ToList();
			Renderer[] array = Object.FindObjectsByType<Renderer>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (Renderer val in array)
			{
				allMaterials.AddRange(val.sharedMaterials.Where((Material mat) => !allMaterials.Contains(mat)));
			}
			int num = Shader.PropertyToID("_MainTex");
			int num2 = Shader.PropertyToID("_CORRUPTTEXTURE");
			Texture2D textureFromPacks = ResourcePacksManager.GetTextureFromPacks("_CORRUPTTEXTURE");
			foreach (Material item in allMaterials)
			{
				if (!((Object)(object)item == (Object)null))
				{
					if (item.HasTexture(num))
					{
						item.mainTexture = item.mainTexture;
					}
					try
					{
						item.SetTexture(num2, (Texture)(object)textureFromPacks);
					}
					catch (Exception data)
					{
						RHLog.Error(data, 100, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					}
				}
			}
			SpriteRenderer[] array2 = Object.FindObjectsByType<SpriteRenderer>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (SpriteRenderer val2 in array2)
			{
				val2.sprite = val2.sprite;
			}
			Image[] array3 = Object.FindObjectsByType<Image>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (Image val3 in array3)
			{
				val3.sprite = val3.sprite;
				val3.overrideSprite = val3.overrideSprite;
			}
		}

		private static void RefreshSounds()
		{
			List<AudioSource> list = Object.FindObjectsByType<AudioSource>((FindObjectsInactive)1, (FindObjectsSortMode)0).ToList();
			foreach (AudioSource item in list)
			{
				AudioSourcePatches.SwapClip(item);
				if (item.isPlaying && (double)item.time < 0.1 && ((Behaviour)item).enabled && ((Component)item).gameObject.activeInHierarchy)
				{
					RHDebugTools.QueueSound(item.clip);
				}
			}
		}

		public void Awake()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			Task.Run((Func<Task?>)ResourcePacksManager.InitLoad);
			InitOfficialCosmeticSystem();
			_mainThreadId = Thread.CurrentThread.ManagedThreadId;
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			RHConfig.InitConfigs();
			if (IsWindows && RHConfig.ColoredConsole)
			{
				AnsiSupport.EnableConsoleColors();
			}
			RHLog.Debug("Patching...", 145, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
			Harmony = new Harmony("monksilly.resourcefulhands");
			Harmony.PatchAll();
			RHLog.Debug("Hooking loaded event...", 149, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
			bool hasLoadedIntro = false;
			SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
			{
				InitOfficialCosmeticSystem();
				targetFps = Application.targetFrameRate;
				RHLog.Debug("Evaluating newly loaded scene...", 155, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
				if (!((Scene)(ref scene)).name.ToLower().Contains("intro") && !hasLoadedIntro)
				{
					hasLoadedIntro = true;
					RHLog.Info("Loading internal assets...", 159, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					AssetBundle? assets = Assets;
					if (assets != null)
					{
						assets.LoadAllAssets();
					}
					if (RHConfig.UseOldSprReplace)
					{
						RHLog.Info("Hooking sprite replacer...", 164, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
						CoroutineDispatcher.AddToUpdate(delegate
						{
							SpriteRenderer[] array = Object.FindObjectsByType<SpriteRenderer>((FindObjectsSortMode)0);
							SpriteRenderer[] array2 = array;
							foreach (SpriteRenderer sr2 in array2)
							{
								SpriteRendererPatches.Patch(sr2);
							}
						});
					}
					else
					{
						RHLog.Info("Queuing sprite replacer...", 175, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
						CoroutineDispatcher.RunOnMainThread(delegate
						{
							<>c__DisplayClass31_1 CS$<>8__locals1 = new <>c__DisplayClass31_1();
							CS$<>8__locals1.spriteRenderers = Object.FindObjectsByType<SpriteRenderer>((FindObjectsSortMode)0);
							CS$<>8__locals1.lastTick = Time.time;
							CS$<>8__locals1.c = null;
							CreateCoroutine();
							CoroutineDispatcher.AddToUpdate(delegate
							{
								if (Time.time - CS$<>8__locals1.lastTick > 8f / 15f)
								{
									RHLog.Warning("Sprite finder thread has been dead for a while, restarting...", 210, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
									CreateCoroutine();
								}
								SpriteRenderer[] spriteRenderers = CS$<>8__locals1.spriteRenderers;
								foreach (SpriteRenderer sr in spriteRenderers)
								{
									SpriteRendererPatches.Patch(sr);
								}
							});
							void CreateCoroutine()
							{
								if (CS$<>8__locals1.c != null)
								{
									CoroutineDispatcher.StopDispatch(CS$<>8__locals1.c);
								}
								CS$<>8__locals1.c = CoroutineDispatcher.Dispatch(PollSpriteRenderers());
							}
							[IteratorStateMachine(typeof(<>c__DisplayClass31_1.<<Awake>g__PollSpriteRenderers|6>d))]
							IEnumerator PollSpriteRenderers()
							{
								//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
								return new <>c__DisplayClass31_1.<<Awake>g__PollSpriteRenderers|6>d(0)
								{
									<>4__this = CS$<>8__locals1
								};
							}
						});
					}
					RHLog.Info("Loading debug tools...", 220, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					RHDebugTools.Create();
				}
				if (hasLoadedIntro)
				{
					RHLog.Info("Checking packs state...", 227, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					if (ResourcePacksManager.HasPacksChanged)
					{
						ResourcePacksManager.ReloadPacks(waitTillReady: false, delegate
						{
							RHSettingsManager.ShowNotice("Packs have been auto reloaded!");
						});
					}
					RHLog.Info("Refreshing custom commands...", 232, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					RHCommands.RefreshCommands();
					RHLog.Info("Loading settings menu...", 235, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					RHSettingsManager.LoadCustomSettings();
					RHLog.Info("Refreshing assets...", 238, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
					RefreshAllAssets();
				}
			};
			RHLog.Message("Resourceful Hands has loaded!", 242, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Plugin.cs");
		}

		private void InitOfficialCosmeticSystem()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)ofHolder))
			{
				ofHolder = new GameObject
				{
					name = "RHCosmeticSystem"
				};
				ofHolder.AddComponent<OF_CosmeticPage>();
				Object.DontDestroyOnLoad((Object)(object)ofHolder);
			}
		}

		internal static void RefreshAllAssets(bool refreshOriginalAssets = true)
		{
			RefreshTextures();
			RefreshSounds();
			if (refreshOriginalAssets)
			{
				OriginalAssetTracker.ClearAll();
			}
		}
	}
	[Serializable]
	public class ResourcePack
	{
		[CompilerGenerated]
		private sealed class <LoadSoundRoutine>d__35 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string filepath;

			public ResourcePack pack;

			public AudioType audioType;

			private string <clipName>5__1;

			private AudioClip <audioClip>5__2;

			private UnityWebRequest <uwr>5__3;

			private DownloadHandlerAudioClip <dh>5__4;

			private Exception <e>5__5;

			private Dictionary<string, AudioClip> <>s__6;

			private bool <>s__7;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadSoundRoutine>d__35(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<clipName>5__1 = null;
				<audioClip>5__2 = null;
				<uwr>5__3 = null;
				<dh>5__4 = null;
				<e>5__5 = null;
				<>s__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: 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_0071: Expected O, but got Unknown
				//IL_0077: Expected O, but got Unknown
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Expected O, but got Unknown
				//IL_00cf: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Invalid comparison between Unknown and I4
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<clipName>5__1 = Path.GetFileNameWithoutExtension(filepath);
					<audioClip>5__2 = null;
					<uwr>5__3 = null;
					<dh>5__4 = null;
					<uwr>5__3 = new UnityWebRequest(filepath, "GET")
					{
						downloadHandler = (DownloadHandler)new DownloadHandlerAudioClip(filepath, audioType)
					};
					<dh>5__4 = (DownloadHandlerAudioClip)<uwr>5__3.downloadHandler;
					<dh>5__4.streamAudio = false;
					<dh>5__4.compressed = true;
					<>2__current = <uwr>5__3.SendWebRequest();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						Result result = <uwr>5__3.result;
						bool flag = result - 2 <= 1;
						if (flag || (Object)(object)<dh>5__4.audioClip == (Object)null)
						{
							RHLog.Error("Error while loading " + <clipName>5__1 + " [at: " + filepath + "]", 412, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
						}
						else
						{
							<audioClip>5__2 = <dh>5__4.audioClip;
						}
					}
					catch (Exception ex)
					{
						<e>5__5 = ex;
						RHLog.Error("Error while loading " + <clipName>5__1 + " [at: " + filepath + "]\n" + <e>5__5.Message, 418, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
					}
					if ((Object)(object)<audioClip>5__2 == (Object)null)
					{
						return false;
					}
					pack.RawSounds.Add(<audioClip>5__2);
					((Object)<audioClip>5__2).name = <clipName>5__1;
					if (ResourcePacksManager.OldNewSpriteNames.ContainsKey(<clipName>5__1))
					{
						<clipName>5__1 = ResourcePacksManager.OldNewSoundNames[<clipName>5__1];
					}
					<>s__6 = pack.Sounds;
					<>s__7 = false;
					try
					{
						Monitor.Enter(<>s__6, ref <>s__7);
						if (!pack.Sounds.TryAdd(<clipName>5__1, <audioClip>5__2))
						{
							RHLog.Error("Failed to add " + <clipName>5__1 + " because sound of that name already exists in the same pack! [at: " + filepath + "]", 431, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
						}
					}
					finally
					{
						if (<>s__7)
						{
							Monitor.Exit(<>s__6);
						}
					}
					<>s__6 = null;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public string name = string.Empty;

		public string desc = string.Empty;

		public string author = string.Empty;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string packVersion = string.Empty;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public ulong steamId = 0uL;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string guid = string.Empty;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public bool hiddenFromList = false;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public bool onlyInFullGame = false;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string gameVersionString = string.Empty;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string relativeTexturesPath = "Textures";

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string relativeSoundsPath = "Sounds";

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string relativeIconPath = "pack.png";

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public bool enableFilter = false;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public int formatVersion = 3;

		[NonSerialized]
		[JsonIgnore]
		public const int CurrentFormatVersion = 3;

		[NonSerialized]
		[JsonIgnore]
		public bool IsActive = true;

		[NonSerialized]
		[JsonIgnore]
		public Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>();

		[NonSerialized]
		[JsonIgnore]
		public Dictionary<string, AudioClip> Sounds = new Dictionary<string, AudioClip>();

		[NonSerialized]
		[JsonIgnore]
		protected List<AudioClip> RawSounds = new List<AudioClip>();

		[NonSerialized]
		[JsonIgnore]
		public bool IsConfigFolderPack = true;

		[NonSerialized]
		[JsonIgnore]
		public const string DefaultJson = "{\r\n    \"name\":\"generated-game-assets\",\r\n    \"desc\":\"Every game asset\",\r\n    \"author\":\"Dark Machine Games\",\r\n    \r\n    \"pack-version\":\"0.50\",\r\n    \"steamid\":0,\r\n    \r\n    \"guid\":\"generated.game.assets.unique\",\r\n    \"hidden-from-list\":true,\r\n    \"only-in-full-game\":false,\r\n    \r\n    \"game-string\":\"b0.50p\",\r\n    \r\n    \"textures-folder\":\"Textures\",\r\n    \"sounds-folder\":\"Sounds\",\r\n    \"icon-file\":\"pack.png\",\r\n    \"icon-filter\":false,\r\n    \r\n    \"format-version\":3\r\n}";

		[JsonIgnore]
		public string PackPath { get; private set; } = string.Empty;


		[JsonIgnore]
		public Texture2D Icon { get; private set; } = null;


		public Texture2D? GetTexture(string textureName)
		{
			Textures.TryGetValue(textureName, out Texture2D value);
			return value;
		}

		public bool HasHandTextures()
		{
			string[] handSpriteNames = RHSpriteManager.HandSpriteNames;
			foreach (string text in handSpriteNames)
			{
				if (Textures.ContainsKey(text))
				{
					return true;
				}
				if (Textures.ContainsKey(RHSpriteManager.GetHandPrefix(0) + text))
				{
					return true;
				}
				if (Textures.ContainsKey(RHSpriteManager.GetHandPrefix(1) + text))
				{
					return true;
				}
			}
			return false;
		}

		public AudioClip? GetSound(string soundName)
		{
			Sounds.TryGetValue(soundName, out AudioClip value);
			return value;
		}

		public static async Task<ResourcePack?> Load(string path, bool force = false)
		{
			bool isConfigPack = path.Contains("config") && path.Contains("RHPacks");
			string jsonPath = Path.Combine(path, "info.json");
			if (!File.Exists(jsonPath))
			{
				RHLog.Warning(path + " doesn't have an info.json!", 202, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				return null;
			}
			ResourcePack pack = JsonConvert.DeserializeObject<ResourcePack>(await File.ReadAllTextAsync(jsonPath));
			if (pack == null)
			{
				RHLog.Warning(jsonPath + " isn't a valid ResourcePack json!", 208, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				RHLog.Info("Example: {\r\n    \"name\":\"generated-game-assets\",\r\n    \"desc\":\"Every game asset\",\r\n    \"author\":\"Dark Machine Games\",\r\n    \r\n    \"pack-version\":\"0.50\",\r\n    \"steamid\":0,\r\n    \r\n    \"guid\":\"generated.game.assets.unique\",\r\n    \"hidden-from-list\":true,\r\n    \"only-in-full-game\":false,\r\n    \r\n    \"game-string\":\"b0.50p\",\r\n    \r\n    \"textures-folder\":\"Textures\",\r\n    \"sounds-folder\":\"Sounds\",\r\n    \"icon-file\":\"pack.png\",\r\n    \"icon-filter\":false,\r\n    \r\n    \"format-version\":3\r\n}", 209, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				return null;
			}
			pack.PackPath = path;
			pack.IsConfigFolderPack = isConfigPack;
			if (!force)
			{
				if (pack.hiddenFromList)
				{
					RHLog.Info("Not loading resource pack at " + path + " because it is hidden.", 219, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
					return null;
				}
				if (pack.onlyInFullGame && Plugin.IsDemo)
				{
					RHLog.Info("Skipping incompatible resource pack (it says it only works for the fullgame): " + path, 224, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
					return null;
				}
			}
			if (pack.formatVersion != 3)
			{
				RHLog.Warning($"Resource pack at {path} is format version {pack.formatVersion} which isn't {3} (the current version), it may not function correctly.", 230, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			}
			string iconPath = Path.Combine(path, pack.relativeIconPath);
			if (!File.Exists(iconPath))
			{
				RHLog.Warning(path + " doesn't have an pack.png! (icon path: '" + pack.relativeIconPath + "')", 235, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				await CoroutineDispatcher.RunOnMainThreadAndWait(delegate
				{
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					pack.Icon = (Texture2D)(((object)Plugin.IconGray) ?? ((object)new Texture2D(2, 2)));
				}, 236, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			}
			else
			{
				byte[] fileBytes2 = await File.ReadAllBytesAsync(iconPath);
				await CoroutineDispatcher.RunOnMainThreadAndWait(delegate
				{
					//IL_0003: Unknown result type (might be due to invalid IL or missing references)
					//IL_0009: Expected O, but got Unknown
					Texture2D val2 = new Texture2D(2, 2);
					if (!ImageConversion.LoadImage(val2, fileBytes2, false))
					{
						RHLog.Warning(iconPath + " isn't a valid texture!", 249, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
						try
						{
							Object.Destroy((Object)(object)val2);
							return;
						}
						catch
						{
							return;
						}
					}
					((Object)val2).name = Path.GetFileNameWithoutExtension(iconPath);
					((Texture)val2).filterMode = (FilterMode)(pack.enableFilter ? 1 : 0);
					val2.Apply();
					pack.Icon = val2;
				}, 244, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			}
			string prevGuid = pack.guid;
			if (string.IsNullOrWhiteSpace(pack.guid))
			{
				pack.guid = pack.author.ToLower() + "." + pack.name.ToLower();
			}
			pack.guid = MiscUtils.CleanString(pack.guid.Replace(' ', '_'));
			if (pack.guid != prevGuid)
			{
				string newJson = JsonConvert.SerializeObject((object)pack, (Formatting)1);
				await File.WriteAllTextAsync(jsonPath, newJson);
				RHLog.Warning("Corrected " + pack.name + "'s guid: " + prevGuid + " -> " + pack.guid, 275, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			}
			ResourcePack conflictingPack = ResourcePacksManager.LoadedPacks.FirstOrDefault((ResourcePack p) => p.guid == pack.guid);
			if (conflictingPack != null)
			{
				RHLog.Error("Resource pack's guid (" + pack.guid + ") at '" + path + "' is the same as the resource pack's guid at '" + conflictingPack.PackPath, 283, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				return null;
			}
			RHLog.Info("Resource pack at " + path + " is valid, loading assets...", 287, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			string texturesFolder = Path.Combine(path, pack.relativeTexturesPath);
			string soundsFolder = Path.Combine(path, pack.relativeSoundsPath);
			RHLog.Debug("Resource pack at " + path + " uses '" + texturesFolder + "' and '" + soundsFolder + "'", 290, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			string[] textureFiles = Array.Empty<string>();
			string[] soundFiles = Array.Empty<string>();
			if (Directory.Exists(texturesFolder))
			{
				textureFiles = Directory.GetFiles(texturesFolder, "*.*", SearchOption.AllDirectories);
			}
			if (Directory.Exists(soundsFolder))
			{
				soundFiles = Directory.GetFiles(soundsFolder, "*.*", SearchOption.AllDirectories);
			}
			int textureCount = textureFiles.Length;
			int i = 0;
			string[] array = textureFiles;
			foreach (string textureFile in array)
			{
				RHLog.Info($"Loading textures ({i++}/{textureCount})", 304, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				string extension = Path.GetExtension(textureFile).ToLower();
				if (!extension.Contains("png") && !extension.Contains("jpg"))
				{
					RHLog.Warning(extension + " isn't supported! Only png and jpg files are supported! [at: " + textureFile + "]", 308, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
					continue;
				}
				byte[] fileBytes = await File.ReadAllBytesAsync(textureFile);
				RHLog.Debug("Texture valid, queuing...", 312, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				await CoroutineDispatcher.RunOnMainThreadAndWait(delegate
				{
					//IL_0003: Unknown result type (might be due to invalid IL or missing references)
					//IL_0009: Expected O, but got Unknown
					Texture2D val = new Texture2D(2, 2);
					if (!ImageConversion.LoadImage(val, fileBytes, false))
					{
						RHLog.Warning(textureFile + " isn't a valid texture!", 318, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
						try
						{
							Object.Destroy((Object)(object)val);
							return;
						}
						catch
						{
							return;
						}
					}
					((Object)val).name = Path.GetFileNameWithoutExtension(textureFile);
					if (ResourcePacksManager.OldNewSpriteNames.ContainsKey(((Object)val).name))
					{
						((Object)val).name = ResourcePacksManager.OldNewSpriteNames[((Object)val).name];
					}
					((Texture)val).filterMode = (FilterMode)0;
					val.Apply();
					if (!pack.Textures.TryAdd(((Object)val).name, val))
					{
						RHLog.Error("Failed to add " + textureFile + " because texture of that name already exists in the same pack!", 329, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
					}
				}, 313, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			}
			await LoadAllSounds(soundFiles, pack);
			return pack;
		}

		private static async Task LoadAllSounds(IEnumerable<string> soundFiles, ResourcePack pack)
		{
			List<Task> soundTasks = new List<Task>();
			List<string> files = soundFiles.ToList();
			int i = 0;
			int soundCount = files.ToList().Count;
			foreach (string soundFile in files)
			{
				int num = i + 1;
				i = num;
				RHLog.Info($"Queuing sounds ({num}/{soundCount})", 349, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
				soundTasks.Add(LoadSound(soundFile, pack));
			}
			await Task.WhenAll(soundTasks);
			RHLog.Info($"Loaded {soundTasks.Count} sounds for {pack.guid}!", 357, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
		}

		private static async Task LoadSound(string filepath, ResourcePack pack)
		{
			string extension = Path.GetExtension(filepath);
			string type = extension.Substring(1, extension.Length - 1);
			string text = type.ToLower();
			if (1 == 0)
			{
			}
			AudioType val = (AudioType)(text switch
			{
				"wav" => 20, 
				"ogg" => 14, 
				"mp3" => 13, 
				"aiff" => 2, 
				"wma" => 13, 
				"acc" => 1, 
				_ => 0, 
			});
			if (1 == 0)
			{
			}
			AudioType audioType = val;
			if ((int)audioType == 0)
			{
				RHLog.Error("Failed to load sound file, '" + type + "' is not a supported format [at: " + filepath + "]", 379, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePack.cs");
			}
			else
			{
				Random rand = new Random();
				await Task.Delay(rand.Next(100, 300));
				CoroutineDispatcher.Dispatch(LoadSoundRoutine(filepath, pack, audioType));
			}
		}

		[IteratorStateMachine(typeof(<LoadSoundRoutine>d__35))]
		private static IEnumerator LoadSoundRoutine(string filepath, ResourcePack pack, AudioType audioType)
		{
			//IL_0015: 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)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadSoundRoutine>d__35(0)
			{
				filepath = filepath,
				pack = pack,
				audioType = audioType
			};
		}
	}
	internal static class OriginalAssetTracker
	{
		internal static List<Object> ModifiedAssets = new List<Object>();

		public static Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>();

		public static Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>();

		public static Dictionary<string, AudioClip> sounds = new Dictionary<string, AudioClip>();

		public static void ClearAll()
		{
			sprites.Clear();
			textures.Clear();
			sounds.Clear();
		}

		public static AudioClip? GetSound(string clipName)
		{
			return sounds.GetValueOrDefault(clipName);
		}

		public static Texture2D? GetTexture(string texName)
		{
			return textures.GetValueOrDefault(texName);
		}

		public static Sprite? GetSprite(string spriteName)
		{
			return sprites.GetValueOrDefault(spriteName);
		}

		public static Sprite? GetFirstSpriteFromTextureName(string textureName)
		{
			string textureName2 = textureName;
			return ((IEnumerable<Sprite>)sprites.Values).FirstOrDefault((Func<Sprite, bool>)((Sprite sprite) => ((Object)sprite.texture).name == textureName2));
		}
	}
	public static class ResourcePacksManager
	{
		private static TaskCompletionSource<bool> _initialLoadSource = new TaskCompletionSource<bool>();

		public static bool HasPacksChanged = true;

		private static Dictionary<string, Tuple<string, string>> _textureOverrides = new Dictionary<string, Tuple<string, string>>();

		private static bool _isReloading;

		private static bool HasLoadedOnInit;

		public static Task InitialLoadTask => _initialLoadSource.Task;

		public static Dictionary<string, string> OldNewSpriteNames
		{
			get
			{
				if (Plugin.IsDemo)
				{
					return new Dictionary<string, string>
					{
						{ "Hands_Background_Sprite_Library_01", "Hands_Sprite_library" },
						{ "Hands_Background_Sprite_Library_02", "Hands_Sprite_Library_02" },
						{ "Hands_Foreground_Sprite_Library_01", "Fingers_Sprite_library" },
						{ "Hands_Foreground_Sprite_Library_02", "Fingers_Sprite_Library_02" }
					};
				}
				return new Dictionary<string, string>
				{
					{ "Hands_Sprite_library", "Hands_Background_Sprite_Library_01" },
					{ "Hands_Sprite_Library_02", "Hands_Background_Sprite_Library_02" },
					{ "Fingers_Sprite_library", "Hands_Foreground_Sprite_Library_01" },
					{ "Fingers_Sprite_Library_02", "Hands_Foreground_Sprite_Library_02" }
				};
			}
		}

		public static Dictionary<string, string> OldNewSoundNames => new Dictionary<string, string> { { "", "" } };

		public static bool IsUsingRHPacksFolder => LoadedPacks.Exists((ResourcePack p) => p.IsConfigFolderPack);

		public static List<ResourcePack> LoadedPacks { get; internal set; } = new List<ResourcePack>();


		public static ResourcePack[] ActivePacks => LoadedPacks.Where((ResourcePack pack) => pack?.IsActive ?? false).ToArray();

		public static ResourcePack? GetPackWithID(string id)
		{
			foreach (ResourcePack loadedPack in LoadedPacks)
			{
				if (loadedPack.guid == id)
				{
					return loadedPack;
				}
			}
			return null;
		}

		public static bool IsPackEnabledWithID(string id)
		{
			ResourcePack[] activePacks = ActivePacks;
			foreach (ResourcePack resourcePack in activePacks)
			{
				if (resourcePack.guid == id)
				{
					return true;
				}
			}
			return false;
		}

		public static bool DoesPackATakePriorityOverPackB(ResourcePack a, ResourcePack b)
		{
			bool flag = false;
			foreach (ResourcePack loadedPack in LoadedPacks)
			{
				if (loadedPack.guid == a.guid)
				{
					flag = true;
				}
				if (loadedPack.guid == b.guid && !flag)
				{
					return true;
				}
			}
			return false;
		}

		public static void AddTextureOverride(string originalTextureName, string newTextureName, string packId)
		{
			_textureOverrides[originalTextureName] = Tuple.Create(newTextureName, packId);
		}

		public static void RemoveTextureOverride(string textureName)
		{
			_textureOverrides.Remove(textureName);
		}

		public static Tuple<string, string>? GetTextureOverride(string textureName)
		{
			return _textureOverrides.GetValueOrDefault(textureName);
		}

		public static ResourcePack? FindPackWithTexture(string textureName)
		{
			ResourcePack result = null;
			ResourcePack[] activePacks = ActivePacks;
			foreach (ResourcePack resourcePack in activePacks)
			{
				Texture2D texture = resourcePack.GetTexture(textureName);
				if ((Object)(object)texture != (Object)null)
				{
					result = resourcePack;
				}
			}
			return result;
		}

		public static Texture2D? GetTextureFromPacks(string textureName, bool nullOnFail = false)
		{
			if (_isReloading)
			{
				if (nullOnFail)
				{
					return null;
				}
				Texture2D texture = OriginalAssetTracker.GetTexture(textureName);
				return Object.op_Implicit((Object)(object)texture) ? texture : null;
			}
			Texture2D val = null;
			if (_textureOverrides.TryGetValue(textureName, out Tuple<string, string> value) && IsPackEnabledWithID(value.Item2))
			{
				ResourcePack packWithID = GetPackWithID(value.Item2);
				if (packWithID != null)
				{
					val = packWithID.GetTexture(value.Item1);
					if ((Object)(object)val == (Object)null)
					{
						val = OriginalAssetTracker.GetTexture(textureName);
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				ResourcePack[] activePacks = ActivePacks;
				foreach (ResourcePack resourcePack in activePacks)
				{
					Texture2D texture2 = resourcePack.GetTexture(textureName);
					if ((Object)(object)texture2 != (Object)null)
					{
						val = texture2;
					}
				}
			}
			Texture2D texture3 = OriginalAssetTracker.GetTexture(textureName);
			if (Object.op_Implicit((Object)(object)val))
			{
				return val;
			}
			if (nullOnFail)
			{
				return null;
			}
			if (Object.op_Implicit((Object)(object)texture3))
			{
				return texture3;
			}
			if ((textureName == "DeathFloor_02" || textureName == "_CORRUPTTEXTURE") ? true : false)
			{
				return Plugin.CorruptionTexture;
			}
			return null;
		}

		public static AudioClip? GetSoundFromPacks(string soundName)
		{
			if (_isReloading)
			{
				AudioClip sound = OriginalAssetTracker.GetSound(soundName);
				return Object.op_Implicit((Object)(object)sound) ? sound : null;
			}
			AudioClip val = null;
			ResourcePack[] activePacks = ActivePacks;
			foreach (ResourcePack resourcePack in activePacks)
			{
				AudioClip sound2 = resourcePack.GetSound(soundName);
				if ((Object)(object)sound2 != (Object)null)
				{
					val = sound2;
				}
			}
			AudioClip sound3 = OriginalAssetTracker.GetSound(soundName);
			if ((Object)(object)val == (Object)null && Object.op_Implicit((Object)(object)sound3))
			{
				return sound3;
			}
			return val;
		}

		internal static void MovePack(ResourcePack pack, bool isUp)
		{
			ResourcePack pack2 = pack;
			int num = LoadedPacks.FindIndex((ResourcePack p) => p == pack2);
			int num2 = (isUp ? Math.Clamp(num - 1, 0, LoadedPacks.Count - 1) : Math.Clamp(num + 1, 0, LoadedPacks.Count - 1));
			if (num2 == num)
			{
				RHLog.Warning("Can't move pack out of range", 237, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				return;
			}
			ResourcePack value = LoadedPacks[num2];
			LoadedPacks[num2] = pack2;
			LoadedPacks[num] = value;
			Save();
		}

		internal static void SaveDisabledPacks()
		{
			if (_isReloading)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (ResourcePack loadedPack in LoadedPacks)
			{
				if (!loadedPack.IsActive)
				{
					list.Add(loadedPack.guid);
				}
			}
			RHConfig.PackPrefs.DisabledPacks = list.ToArray();
			RHConfig.PackPrefs.Save();
		}

		internal static void LoadDisabledPacks()
		{
			if (_isReloading)
			{
				return;
			}
			RHConfig.PackPrefs.Load();
			string[] disabledPacks = RHConfig.PackPrefs.DisabledPacks;
			if (disabledPacks.Length == 0)
			{
				return;
			}
			string[] array = disabledPacks;
			foreach (string disabledPackGuid in array)
			{
				RHLog.Debug(disabledPackGuid + " is a disabled pack.", 271, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				foreach (ResourcePack item in LoadedPacks.Where((ResourcePack pack) => pack.guid == disabledPackGuid))
				{
					item.IsActive = false;
				}
			}
		}

		internal static void SavePackOrder()
		{
			if (!_isReloading)
			{
				string[] array = new string[LoadedPacks.Count];
				for (int i = 0; i < LoadedPacks.Count; i++)
				{
					ResourcePack resourcePack = LoadedPacks[i];
					array[i] = resourcePack.guid;
				}
				RHConfig.PackPrefs.PackOrder = array;
				RHConfig.PackPrefs.Save();
			}
		}

		internal static void LoadPackOrder()
		{
			if (_isReloading)
			{
				return;
			}
			RHConfig.PackPrefs.Load();
			string[] packOrder = RHConfig.PackPrefs.PackOrder;
			ResourcePack[] array = LoadedPacks.ToArray();
			ResourcePack[] array2 = new ResourcePack[packOrder.Length];
			for (int i = 0; i < array2.Length; i++)
			{
				array2[i] = null;
			}
			for (int j = 0; j < packOrder.Length; j++)
			{
				string guid = packOrder[j];
				ResourcePack resourcePack = array.FirstOrDefault((ResourcePack p) => p.guid == guid);
				if (resourcePack != null)
				{
					array2[j] = resourcePack;
				}
			}
			List<ResourcePack> list = new List<ResourcePack>();
			ResourcePack[] array3 = array2;
			foreach (ResourcePack resourcePack2 in array3)
			{
				if (resourcePack2 != null)
				{
					list.Add(resourcePack2);
				}
			}
			ResourcePack[] array4 = array;
			foreach (ResourcePack item in array4)
			{
				if (!list.Contains(item))
				{
					list.Add(item);
				}
			}
			LoadedPacks = list;
		}

		public static void Save()
		{
			SavePackOrder();
			SaveDisabledPacks();
		}

		public static bool ReloadPacks(bool waitTillReady = false, Action? callback = null)
		{
			Action callback2 = callback;
			if (_isReloading && !waitTillReady)
			{
				RHLog.Warning("Tried to reload while already reloading?", 335, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				return false;
			}
			RHLog.Debug("Dispatching pack reloader task...", 339, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
			Task.Run(async delegate
			{
				if (_isReloading && waitTillReady)
				{
					RHLog.Debug("Waiting for previous reload...", 344, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
					while (_isReloading)
					{
						await Task.Delay(125);
					}
					RHLog.Debug("Reloading...", 347, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				}
				await ReloadPacks_Internal();
				if (callback2 != null)
				{
					CoroutineDispatcher.RunOnMainThread(callback2);
				}
			});
			return true;
		}

		public static async Task InitLoad()
		{
			RHLog.Info("Initializing loading...", 361, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
			if (HasLoadedOnInit)
			{
				RHLog.Warning("Tried to Init while it's already initialized?", 364, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				return;
			}
			_isReloading = false;
			await ReloadPacks_Internal();
			RHLog.Info("Initialized loading.", 370, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
		}

		internal static async Task ReloadPacks_Internal()
		{
			if (_isReloading)
			{
				return;
			}
			HasPacksChanged = false;
			if (LoadedPacks.Count != 0)
			{
				RHLog.Debug("Saving packs before reloading!", 380, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				Save();
			}
			_isReloading = true;
			LoadedPacks.Clear();
			RHLog.Info("Expanding zips in " + RHConfig.PacksFolder + "...", 386, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
			string[] zipPaths = Directory.GetFiles(RHConfig.PacksFolder, "*.zip", SearchOption.TopDirectoryOnly);
			string[] array = zipPaths;
			foreach (string zipPath in array)
			{
				try
				{
					RHLog.Info("Expanding resource pack zip: " + zipPath, 392, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
					bool isTopLevelZip;
					using (ZipArchive zip = ZipFile.OpenRead(zipPath))
					{
						isTopLevelZip = zip.GetEntry("info.json") != null;
					}
					if (isTopLevelZip)
					{
						DirectoryInfo zipTargDir = Directory.CreateDirectory(Path.Combine(RHConfig.PacksFolder, Path.GetFileNameWithoutExtension(zipPath)));
						ZipFile.ExtractToDirectory(zipPath, zipTargDir.FullName);
					}
					else
					{
						ZipFile.ExtractToDirectory(zipPath, RHConfig.PacksFolder);
					}
					File.Delete(zipPath);
					RHLog.Info("Expanded!", 406, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				}
				catch (Exception e)
				{
					RHLog.Info("Failed to expand!", 410, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
					RHLog.Error(e, 411, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				}
			}
			RHLog.Info("Loading resource packs...", 414, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
			List<string> paths = new List<string>();
			paths.AddRange(Directory.GetDirectories(RHConfig.PacksFolder, "*", SearchOption.TopDirectoryOnly));
			paths.AddRange(Directory.GetDirectories(Paths.PluginPath, "*", SearchOption.AllDirectories));
			int failedPacks = 0;
			foreach (string path in paths)
			{
				if (!File.Exists(Path.Combine(path, "info.json")))
				{
					continue;
				}
				try
				{
					RHLog.Info("Loading resource pack: " + path, 428, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
					ResourcePack pack = await ResourcePack.Load(path);
					if (pack == null)
					{
						RHLog.Warning("Failed to load pack at " + path + "!", 432, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
						failedPacks++;
					}
					else
					{
						LoadedPacks.Add(pack);
						RHLog.Info("Loaded!", 438, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
					}
				}
				catch (Exception ex)
				{
					Exception e2 = ex;
					failedPacks++;
					RHLog.Info("Failed to load!", 443, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
					RHLog.Error(e2, 444, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				}
			}
			RHLog.Info($"Loaded {LoadedPacks.Count}/{LoadedPacks.Count + failedPacks} resource packs", 448, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
			if (failedPacks > 0)
			{
				RHLog.Warning($"{failedPacks} packs failed to load!", 450, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
			}
			await CoroutineDispatcher.RunOnMainThreadAndWait(delegate
			{
				_isReloading = false;
				RHLog.Info("Re-ordering to user order...", 456, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				LoadPackOrder();
				RHLog.Info("Disabling packs that should be disabled...", 458, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
				LoadDisabledPacks();
				Plugin.RefreshAllAssets(refreshOriginalAssets: false);
				if (Object.op_Implicit((Object)(object)UI_RHPacksList.Instance))
				{
					UI_RHPacksList.Instance?.BuildList();
				}
				_initialLoadSource.TrySetResult(result: true);
			}, 452, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/ResourcePacksManager.cs");
		}
	}
	public class RHSpriteManager
	{
		private static Dictionary<string, Sprite> _customSpriteCache = new Dictionary<string, Sprite>();

		private static Dictionary<string, Sprite> _customHandCache = new Dictionary<string, Sprite>();

		public static string[] HandSpriteNames
		{
			get
			{
				if (Plugin.IsDemo)
				{
					return new string[4] { "Hands_Sprite_library", "Hands_Sprite_Library_02", "Fingers_Sprite_library", "Fingers_Sprite_Library_02" };
				}
				return new string[9] { "Hands_Background_Sprite_Library_01", "Hands_Background_Sprite_Library_02", "Hands_Background_Sprite_Library_03", "Hands_Foreground_Sprite_Library_01", "Hands_Foreground_Sprite_Library_02", "Hands_Foreground_Sprite_Library_03", "Hands_Foreground_Sprite_Library_03", "Perk_handPoses", "milk_fingers" };
			}
		}

		public static void OverrideHands(string packId, bool isLeft)
		{
			string text = (isLeft ? GetHandPrefix(0) : GetHandPrefix(1));
			string[] handSpriteNames = HandSpriteNames;
			foreach (string text2 in handSpriteNames)
			{
				ResourcePacksManager.AddTextureOverride(text + text2, text2, packId);
			}
			ResourcePacksManager.AddTextureOverride(text + "hand-sheet", "hand-sheet", packId);
		}

		public static void ClearHandsOverride(bool isLeft)
		{
			string text = (isLeft ? GetHandPrefix(0) : GetHandPrefix(1));
			string[] handSpriteNames = HandSpriteNames;
			foreach (string text2 in handSpriteNames)
			{
				ResourcePacksManager.RemoveTextureOverride(text + text2);
			}
			ResourcePacksManager.RemoveTextureOverride(text + "hand-sheet");
		}

		public static string GetHandsOverride(bool isLeft)
		{
			string[] handSpriteNames = HandSpriteNames;
			int num = 0;
			if (num < handSpriteNames.Length)
			{
				string text = handSpriteNames[num];
				return ResourcePacksManager.GetTextureOverride((isLeft ? GetHandPrefix(0) : GetHandPrefix(1)) + text)?.Item2 ?? string.Empty;
			}
			return string.Empty;
		}

		public static bool IsHandSprite(Sprite sprite)
		{
			if ((Object)(object)sprite == (Object)null)
			{
				return false;
			}
			string name = ((Object)sprite).name.ToLower();
			return Array.Exists(HandSpriteNames, (string s) => string.Equals(s, name, StringComparison.CurrentCultureIgnoreCase));
		}

		public static bool IsHandRenderer(SpriteRenderer spriteRenderer)
		{
			if ((Object)(object)spriteRenderer == (Object)null)
			{
				return false;
			}
			Transform val = MiscUtils.FindParentWithName(((Component)spriteRenderer).transform, "Inventory-Root");
			return (Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val);
		}

		public static bool IsRightHand(SpriteRenderer spriteRenderer)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spriteRenderer == (Object)null)
			{
				return false;
			}
			Transform val = MiscUtils.FindChildWithParentNamed(((Component)spriteRenderer).transform, "Inventory-Root");
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			return val.localPosition.x > 0f;
		}

		public static string GetHandPrefix(SpriteRenderer spriteRenderer)
		{
			if ((Object)(object)spriteRenderer == (Object)null)
			{
				return "Left_";
			}
			return IsRightHand(spriteRenderer) ? "Right_" : "Left_";
		}

		public static string GetHandPrefix(int id)
		{
			return (id == 0) ? "Left_" : "Right_";
		}

		public static void ClearSpriteCache()
		{
			_customSpriteCache.Clear();
			_customHandCache.Clear();
		}

		public static void ClearSpecificSprite(string key)
		{
			_customSpriteCache.Remove(key);
			_customHandCache.Remove(key);
		}

		public static void ClearHandSprites()
		{
			_customHandCache.Clear();
			List<string> list = new List<string>();
			list.AddRange(_customSpriteCache.Where<KeyValuePair<string, Sprite>>(delegate(KeyValuePair<string, Sprite> kv)
			{
				KeyValuePair<string, Sprite> keyValuePair2 = kv;
				return IsHandSprite(keyValuePair2.Value);
			}).Select(delegate(KeyValuePair<string, Sprite> kv)
			{
				KeyValuePair<string, Sprite> keyValuePair = kv;
				return keyValuePair.Key;
			}));
			foreach (string item in list)
			{
				_customSpriteCache.Remove(item);
			}
		}

		public static Sprite? GetReplacementSpriteForRenderer(SpriteRenderer spriteRenderer)
		{
			Sprite sprite = spriteRenderer.sprite;
			if ((Object)(object)sprite == (Object)null)
			{
				return null;
			}
			string name = ((Object)sprite.texture).name;
			if (IsHandRenderer(spriteRenderer))
			{
				string handPrefix = GetHandPrefix(spriteRenderer);
				string text = name;
				if (!text.StartsWith(handPrefix))
				{
					text = handPrefix + text;
				}
				if ((RHConfig.PackPrefs.GetLeftHandPack() == null && handPrefix == GetHandPrefix(0)) || (RHConfig.PackPrefs.GetRightHandPack() == null && handPrefix == GetHandPrefix(1)))
				{
					return null;
				}
				Texture2D textureFromPacks = ResourcePacksManager.GetTextureFromPacks(text);
				if ((Object)(object)textureFromPacks != (Object)null)
				{
					string name2 = ((Object)sprite).name;
					string text2 = ((Object)sprite).name;
					if (!text2.StartsWith(handPrefix))
					{
						text2 = handPrefix + text2;
					}
					if (_customHandCache.TryGetValue(text2, out Sprite value) && (Object)(object)textureFromPacks == (Object)(object)value.texture)
					{
						return value;
					}
					((Object)sprite).name = text2;
					Sprite replacementSprite = GetReplacementSprite(sprite, text);
					((Object)sprite).name = name2;
					if ((Object)(object)replacementSprite != (Object)null)
					{
						_customHandCache[text2] = replacementSprite;
						return replacementSprite;
					}
				}
			}
			return GetReplacementSprite(sprite);
		}

		public static Sprite? GetReplacementSprite(Sprite sprite, string? textureNameOverride = null)
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprite == (Object)null || (Object)(object)sprite.texture == (Object)null)
			{
				return sprite;
			}
			bool flag = OriginalAssetTracker.ModifiedAssets.Contains((Object)(object)sprite) || _customSpriteCache.ContainsValue(sprite);
			string name = ((Object)sprite).name;
			string textureName = textureNameOverride ?? ((Object)sprite.texture).name;
			Sprite val = null;
			if (_customSpriteCache.TryGetValue(name, out Sprite value))
			{
				if ((Object)(object)value != (Object)null)
				{
					val = value;
				}
				else
				{
					RHLog.Debug(name + " is null now for some reason [cached]", 216, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/SpriteManager.cs");
					_customSpriteCache.Remove(name);
				}
			}
			Texture2D textureFromPacks = ResourcePacksManager.GetTextureFromPacks(textureName);
			if ((Object)(object)textureFromPacks == (Object)null)
			{
				return val ?? sprite;
			}
			if ((Object)(object)val != (Object)null && (Object)(object)val.texture == (Object)(object)textureFromPacks)
			{
				return val;
			}
			RHLog.Debug($"Regenerating new sprite for {sprite} because the texture changed.", 226, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/SpriteManager.cs");
			Rect rect = sprite.rect;
			float num = Mathf.Clamp(((Rect)(ref rect)).x, 0f, (float)((Texture)textureFromPacks).width);
			rect = sprite.rect;
			float num2 = Mathf.Clamp(((Rect)(ref rect)).y, 0f, (float)((Texture)textureFromPacks).height);
			rect = sprite.rect;
			float num3 = Mathf.Clamp(((Rect)(ref rect)).width, 0f, (float)((Texture)textureFromPacks).width - num);
			rect = sprite.rect;
			float num4 = Mathf.Clamp(((Rect)(ref rect)).height, 0f, (float)((Texture)textureFromPacks).height - num2);
			Rect val2 = new Rect(num, num2, num3, num4);
			float x = sprite.pivot.x;
			rect = sprite.rect;
			float num5 = x / ((Rect)(ref rect)).width;
			float y = sprite.pivot.y;
			rect = sprite.rect;
			Sprite val3 = Sprite.Create(textureFromPacks, val2, new Vector2(num5, y / ((Rect)(ref rect)).height), sprite.pixelsPerUnit);
			((Object)val3).name = name;
			OriginalAssetTracker.ModifiedAssets.Add((Object)(object)val3);
			if (!flag)
			{
				RHLog.Debug($"{sprite} is being replaced, assuming its an original sprite we are caching it", 240, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/SpriteManager.cs");
				Texture2D texture = sprite.texture;
				if ((Object)(object)texture == (Object)null)
				{
					RHLog.Warning($"{sprite} has no texture", 243, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/SpriteManager.cs");
				}
				else
				{
					OriginalAssetTracker.textures.TryAdd(((Object)texture).name, texture);
					OriginalAssetTracker.sprites.TryAdd(((Object)sprite).name, sprite);
				}
			}
			RHLog.Debug($"cached new replacement {name} as {val3}", 250, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Assets/SpriteManager.cs");
			_customSpriteCache.Remove(name);
			_customSpriteCache.Add(name, val3);
			return val3;
		}
	}
	public class RHDebugTools : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <_queueSound>d__7 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public AudioClip clip;

			public bool force;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <_queueSound>d__7(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (!force && PlayingClips.Contains(clip))
					{
						return false;
					}
					PlayingClips.Add(clip);
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (Object.op_Implicit((Object)(object)clip))
					{
						PlayingClips.Remove(clip);
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static RHDebugTools? Instance;

		public static bool isOn;

		private static readonly List<AudioClip> PlayingClips = new List<AudioClip>();

		private GUIStyle _style = GUIStyle.none;

		private bool _enableNextFrame;

		internal static void Create()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Instance = new GameObject("DebugTools").AddComponent<RHDebugTools>();
			Object.DontDestroyOnLoad((Object)(object)Instance);
		}

		public static void QueueSound(AudioClip clip, bool force = false)
		{
			CoroutineDispatcher.Dispatch(_queueSound(clip, force));
		}

		[IteratorStateMachine(typeof(<_queueSound>d__7))]
		private static IEnumerator _queueSound(AudioClip clip, bool force)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <_queueSound>d__7(0)
			{
				clip = clip,
				force = force
			};
		}

		public void Awake()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			//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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0064: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			else
			{
				Object.Destroy((Object)(object)this);
			}
			if (RHConfig.AlwaysDebug)
			{
				isOn = true;
			}
			_style = new GUIStyle
			{
				fontSize = 32,
				fontStyle = (FontStyle)1,
				normal = new GUIStyleState
				{
					textColor = Color.white
				}
			};
			SceneManager.sceneUnloaded += delegate
			{
				_enableNextFrame |= isOn;
				isOn = false;
			};
			SceneManager.sceneLoaded += delegate(Scene _, LoadSceneMode mode)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Invalid comparison between Unknown and I4
				if ((int)mode <= 0)
				{
					PlayingClips.Clear();
					_enableNextFrame |= isOn;
					isOn = false;
				}
			};
		}

		public void OnGUI()
		{
			//IL_0012: 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_0018: 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)
			if (!isOn)
			{
				return;
			}
			Color contentColor = GUI.contentColor;
			GUI.contentColor = Color.white;
			GUILayout.Label("Recent sounds:", _style, Array.Empty<GUILayoutOption>());
			for (int num = PlayingClips.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)PlayingClips[num] == (Object)null)
				{
					PlayingClips.RemoveAt(num);
				}
			}
			foreach (AudioClip playingClip in PlayingClips)
			{
				GUILayout.Label(((Object)playingClip).name, _style, Array.Empty<GUILayoutOption>());
			}
			GUI.contentColor = contentColor;
		}

		public void LateUpdate()
		{
			if (_enableNextFrame)
			{
				isOn = true;
				_enableNextFrame = false;
			}
		}
	}
	[HarmonyPatch(typeof(Object))]
	public static class DEBUG_InstantiatePatches
	{
		private static void OnInstantiated(Object result, Object original)
		{
			if (!Object.op_Implicit(result))
			{
				return;
			}
			GameObject val = (GameObject)(object)((result is GameObject) ? result : null);
			if (val == null)
			{
				Component val2 = (Component)(object)((result is Component) ? result : null);
				if (val2 != null)
				{
					Component[] componentsInChildren = val2.GetComponentsInChildren<Component>();
					Component[] array = componentsInChildren;
					foreach (Component obj2 in array)
					{
						PatchObject((Object)(object)obj2);
					}
				}
			}
			else
			{
				Component[] componentsInChildren2 = val.GetComponentsInChildren<Component>();
				Component[] array2 = componentsInChildren2;
				foreach (Component obj3 in array2)
				{
					PatchObject((Object)(object)obj3);
				}
			}
			static void PatchObject(Object obj)
			{
				AudioSource val3 = (AudioSource)(object)((obj is AudioSource) ? obj : null);
				if (val3 != null && val3 != null && ((Behaviour)val3).isActiveAndEnabled && val3.playOnAwake)
				{
					RHDebugTools.QueueSound(val3.clip);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("Instantiate", new Type[] { typeof(Object) })]
		private static void Postfix_1(Object __result, Object original)
		{
			OnInstantiated(__result, original);
		}

		[HarmonyPostfix]
		[HarmonyPatch("Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Scene)
		})]
		private static void Postfix_2(Object __result, Object original)
		{
			OnInstantiated(__result, original);
		}

		[HarmonyPostfix]
		[HarmonyPatch("Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Transform)
		})]
		private static void Postfix_3(Object __result, Object original)
		{
			OnInstantiated(__result, original);
		}

		[HarmonyPostfix]
		[HarmonyPatch("Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Transform),
			typeof(bool)
		})]
		private static void Postfix_4(Object __result, Object original)
		{
			OnInstantiated(__result, original);
		}

		[HarmonyPostfix]
		[HarmonyPatch("Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Vector3),
			typeof(Quaternion)
		})]
		private static void Postfix_5(Object __result, Object original)
		{
			OnInstantiated(__result, original);
		}

		[HarmonyPostfix]
		[HarmonyPatch("Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Vector3),
			typeof(Quaternion),
			typeof(Transform)
		})]
		private static void Postfix_6(Object __result, Object original)
		{
			OnInstantiated(__result, original);
		}
	}
	[HarmonyPatch(typeof(AudioSource))]
	[HarmonyPriority(200)]
	public static class DEBUG_AudioSourcePatches
	{
		[HarmonyPatch("Play", new Type[] { })]
		[HarmonyPrefix]
		private static void Play_NoArgs_Postfix(AudioSource __instance)
		{
			LogClip(__instance);
		}

		[HarmonyPatch("Play", new Type[] { typeof(double) })]
		[HarmonyPrefix]
		private static void Play_DelayDouble_Postfix(AudioSource __instance)
		{
			LogClip(__instance);
		}

		[HarmonyPatch("Play", new Type[] { typeof(ulong) })]
		[HarmonyPrefix]
		private static void Play_DelayUlong_Postfix(AudioSource __instance)
		{
			LogClip(__instance);
		}

		[HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip) })]
		[HarmonyPrefix]
		private static void PlayOneShot_ClipOnly_Postfix(AudioSource __instance, ref AudioClip __0)
		{
			LogClip(null, __0);
		}

		[HarmonyPatch("PlayOneShot", new Type[]
		{
			typeof(AudioClip),
			typeof(float)
		})]
		[HarmonyPrefix]
		private static void PlayOneShot_ClipAndVolume_Postfix(AudioSource __instance, ref AudioClip __0)
		{
			LogClip(null, __0);
		}

		private static void LogClip(AudioSource src = null, AudioClip clip = null)
		{
			if (RHDebugTools.isOn && Object.op_Implicit((Object)(object)clip))
			{
				if (Object.op_Implicit((Object)(object)src))
				{
					clip = src.clip;
				}
				RHDebugTools.QueueSound(clip);
			}
		}
	}
	public static class AnsiSupport
	{
		private const int STD_OUTPUT_HANDLE = -11;

		private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4u;

		[DllImport("kernel32.dll", SetLastError = true)]
		private static extern IntPtr GetStdHandle(int nStdHandle);

		[DllImport("kernel32.dll")]
		private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

		[DllImport("kernel32.dll")]
		private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

		public static void EnableConsoleColors()
		{
			RHLog.Info("Enabling console colors...", 26, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Debug/Logger.cs");
			IntPtr stdHandle = GetStdHandle(-11);
			if (stdHandle == IntPtr.Zero)
			{
				RHLog.Warning("Could not get console.", 30, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Debug/Logger.cs");
				return;
			}
			if (!GetConsoleMode(stdHandle, out var lpMode))
			{
				RHLog.Warning("Could not get console mode.", 36, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Debug/Logger.cs");
				return;
			}
			lpMode |= 4u;
			if (!SetConsoleMode(stdHandle, lpMode))
			{
				RHLog.Warning("Could not enable virtual terminal processing.", 43, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Debug/Logger.cs");
				return;
			}
			RHLog.EnableColors = true;
			RHLog.Info("Console colors enabled!", 48, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/Debug/Logger.cs");
		}
	}
	public static class RHLog
	{
		public static class Player
		{
			private static void Message(string message)
			{
				CommandConsole.Log("[Resourceful Hands] " + message, true);
			}

			public static void Info(string message)
			{
				Message(message);
			}

			public static void Warning(string message)
			{
				Message("[Resourceful Hands] [WARNING] " + message);
			}

			public static void Error(string message)
			{
				CommandConsole.LogError("[Resourceful Hands] " + message);
			}
		}

		internal static bool EnableColors;

		private const string Prefix = "[Resourceful Hands] ";

		public static string Reset => EnableColors ? "\u001b[0m" : "";

		public static string Blue => EnableColors ? "\u001b[34m" : "";

		public static string Magenta => EnableColors ? "\u001b[35m" : "";

		public static string Cyan => EnableColors ? "\u001b[36m" : "";

		[Conditional("DEBUG")]
		public static void Debug(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			string file2 = file;
			object data2 = data;
			CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate
			{
				Plugin.Log.LogInfo((object)$"{Magenta}[{Path.GetFileName(file2)}:{lineNumber}] {data2}");
			});
		}

		public static void Info(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			string file2 = file;
			object data2 = data;
			CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate
			{
				Plugin.Log.LogInfo((object)$"{Cyan}[{Path.GetFileName(file2)}:{lineNumber}] {data2}");
			});
		}

		public static void Message(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			string file2 = file;
			object data2 = data;
			CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate
			{
				Plugin.Log.LogMessage((object)$"{Blue}[{Path.GetFileName(file2)}:{lineNumber}] {data2}");
			});
		}

		public static void Warning(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			string file2 = file;
			object data2 = data;
			CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate
			{
				Plugin.Log.LogWarning((object)$"[{Path.GetFileName(file2)}:{lineNumber}] {data2}");
			});
		}

		public static void Error(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			string file2 = file;
			object data2 = data;
			CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate
			{
				Plugin.Log.LogError((object)$"[{Path.GetFileName(file2)}:{lineNumber}] {data2}");
			});
		}
	}
	public class OF_CosmeticPage : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <InitializeCosmeticsRoutine>d__17 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public OF_CosmeticPage <>4__this;

			private Task <packTask>5__1;

			private GameObject <candidate>5__2;

			private UI_CosmeticsMenu <menu>5__3;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitializeCosmeticsRoutine>d__17(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<packTask>5__1 = null;
				<candidate>5__2 = null;
				<menu>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					RHLog.Info("Waiting for Resource Packs to finish loading...", 75, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
					<packTask>5__1 = ResourcePacksManager.InitialLoadTask;
					goto IL_006f;
				case 1:
					<>1__state = -1;
					goto IL_006f;
				case 2:
					<>1__state = -1;
					goto IL_00ce;
				case 3:
					{
						<>1__state = -1;
						break;
					}
					IL_006f:
					if (!<packTask>5__1.IsCompleted)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					RHLog.Info("Packs loaded. Now waiting for Unity Cosmetics Menu to initialize...", 83, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
					<candidate>5__2 = null;
					goto IL_00ce;
					IL_00ce:
					if ((Object)(object)<candidate>5__2 == (Object)null)
					{
						<candidate>5__2 = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Other/Cosmetics");
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 2;
						return true;
					}
					<menu>5__3 = <candidate>5__2.GetComponent<UI_CosmeticsMenu>();
					break;
				}
				if ((Object)(object)<menu>5__3 == (Object)null || <menu>5__3.cosmeticPages == null)
				{
					<>2__current = null;
					<>1__state = 3;
					return true;
				}
				RHLog.Info("Game UI ready. Injecting RH Cosmetic Page...", 99, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				<>4__this.FindCosmeticsTemplate();
				<>4__this.PrepareCosmeticPage();
				<>4__this.PrepareCosmetics();
				<>4__this.IsReady = true;
				RHLog.Info("RH Cosmetics are ready.", 106, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static OF_CosmeticPage instance;

		private CosmeticPage? cosmeticPage;

		private GameObject? cosmeticsMenuObject;

		private UI_CosmeticsMenu? cosmeticsMenu;

		private UI_Page? pageTemplate;

		private UI_PageHolder? pageHolder;

		private GameObject? RHPage;

		private Tab? RHTab;

		public List<Cosmetic_Base> RHHands = new List<Cosmetic_Base>();

		public bool IsReady { get; private set; } = false;


		private void Awake()
		{
			if (!Object.op_Implicit((Object)(object)instance))
			{
				instance = this;
				SceneManager.sceneLoaded -= OnSceneLoadedDelegate;
				SceneManager.sceneLoaded += OnSceneLoadedDelegate;
			}
			else
			{
				RHLog.Warning("Destroying Duplicate Cosmetics Page Manager", 36, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void OnSceneLoadedDelegate(Scene scene, LoadSceneMode mode)
		{
			OnSceneLoaded(((Scene)(ref scene)).name);
		}

		private void OnSceneLoaded(string sceneName)
		{
			if (!((Object)(object)instance != (Object)(object)this))
			{
				if (sceneName != "Main-Menu")
				{
					cosmeticPage = null;
					cosmeticsMenuObject = null;
					cosmeticsMenu = null;
					pageTemplate = null;
					RHPage = null;
					RHTab = null;
					((MonoBehaviour)instance).StopAllCoroutines();
				}
				else if (!Object.op_Implicit((Object)(object)RHPage))
				{
					((MonoBehaviour)instance).StartCoroutine(InitializeCosmeticsRoutine());
				}
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoadedDelegate;
		}

		[IteratorStateMachine(typeof(<InitializeCosmeticsRoutine>d__17))]
		private IEnumerator InitializeCosmeticsRoutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InitializeCosmeticsRoutine>d__17(0)
			{
				<>4__this = this
			};
		}

		private void FindCosmeticsTemplate()
		{
			if (Object.op_Implicit((Object)(object)cosmeticsMenuObject) && Object.op_Implicit((Object)(object)cosmeticsMenu))
			{
				return;
			}
			RHLog.Debug("Finding Cosmetics Template", 114, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
			GameObject val = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Other/Cosmetics");
			if (!Object.op_Implicit((Object)(object)val))
			{
				RHLog.Error("Cosmetics template game object not found", 118, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				return;
			}
			UI_CosmeticsMenu component = val.GetComponent<UI_CosmeticsMenu>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				RHLog.Error("Cosmetics menu template not found", 124, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				return;
			}
			RHLog.Debug("Cosmetics template found", 127, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
			cosmeticsMenuObject = val;
			cosmeticsMenu = component;
		}

		private void PrepareCosmeticPage()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_009b: Expected O, but got Unknown
			if (cosmeticPage == null)
			{
				CosmeticPage val = cosmeticsMenu?.cosmeticPages.Find((CosmeticPage p) => p.cosmeticType == "hand");
				RHLog.Error($"Cosmetic page: {val} | ", 213, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				cosmeticPage = new CosmeticPage
				{
					name = "Hands",
					cosmeticType = "hand",
					pageHolder = val?.pageHolder
				};
			}
		}

		public void PrepareCosmetics()
		{
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Expected O, but got Unknown
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Expected O, but got Unknown
			ResourcefulHandsPatches.CL_CosmeticManager_Patches.ScanVanillaCosmeticsInPlugins();
			if (RHHands.Count > 0)
			{
				return;
			}
			foreach (ResourcePack loadedPack in ResourcePacksManager.LoadedPacks)
			{
				bool flag = false;
				foreach (KeyValuePair<string, Texture2D> texture in loadedPack.Textures)
				{
					if (!texture.Key.Contains("Sprite_Library"))
					{
						continue;
					}
					flag = true;
					break;
				}
				if (!flag)
				{
					continue;
				}
				RHLog.Debug("Loading " + loadedPack.name + " in Experimental Menu", 244, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				Cosmetic_HandItem val = ScriptableObject.CreateInstance<Cosmetic_HandItem>();
				((Object)val).name = loadedPack.name;
				val.currentEmoteIds = new List<int>(2) { 0, 0 };
				val.currentPaletteId = 0;
				Sprite val2 = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name == "card-blank-foreground"));
				RHLog.Debug($"Card template: {val2}", 251, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				Texture2D tex = TextureCompositor.CreatePackCard(loadedPack.Icon, TextureCompositor.SpriteToTexture(val2));
				((Cosmetic_Base)val).cosmeticInfo = new Cosmetic_Info
				{
					id = loadedPack.guid,
					cosmeticName = loadedPack.name,
					tag = "hand",
					author = loadedPack.author,
					description = loadedPack.desc,
					unlock = "",
					cardForeground = TextureCompositor.TextureToSprite(tex)
				};
				val.cosmeticData = new Cosmetic_HandItem_Data
				{
					swapSprites = new List<SwapSprite>(),
					cosmeticName = loadedPack.name,
					author = loadedPack.author,
					description = loadedPack.desc,
					unlock = "",
					id = loadedPack.guid
				};
				Dictionary<string, SwapSprite> dictionary = new Dictionary<string, SwapSprite>();
				Dictionary<string, InteractSwap> dictionary2 = new Dictionary<string, InteractSwap>();
				RHLog.Debug("Loading swaps", 280, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				foreach (KeyValuePair<string, Texture2D> texture2 in loadedPack.Textures)
				{
					if (texture2.Value == null)
					{
						continue;
					}
					if (texture2.Key.Contains("Sprite_Library"))
					{
						int layer = int.Parse(texture2.Key.Split('_')[^1]);
						DynamicHandSlicer.SheetType sheetType = ((!texture2.Key.Contains("Background")) ? DynamicHandSlicer.SheetType.Foreground : DynamicHandSlicer.SheetType.Background);
						Dictionary<Vector2, Texture2D> slices = DynamicHandSlicer.SliceSheet(texture2.Value, 4, 4);
						Dictionary<string, Texture2D> namedSlicesFromSlicedSheet = DynamicHandSlicer.GetNamedSlicesFromSlicedSheet(sheetType, slices, layer);
						foreach (KeyValuePair<string, Texture2D> item in namedSlicesFromSlicedSheet)
						{
							string key = item.Key;
							Texture2D value = item.Value;
							RHLog.Debug(key ?? "", 296, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
							SwapSprite val3 = new SwapSprite
							{
								framerate = 1f,
								hand = -1,
								loopTimeOffset = 0f,
								offset = Vector2.zero
							};
							Sprite val4 = TextureCompositor.TextureToSprite(value);
							((Object)val4).name = key;
							val3.materialBase = "";
							val3.replacementSpriteNames = new List<string>(1) { key };
							val3.replacementSprites = new List<Sprite>(1) { val4 };
							val3.rotation = 0f;
							val3.scale = 1f;
							val3.secondaryTextures = new List<SecondaryTextures>();
							val3.spriteName = key;
							val3.usePalette = true;
							dictionary.TryAdd(val3.spriteName, val3);
						}
					}
					if (!texture2.Key.Contains("hand-sheet"))
					{
						continue;
					}
					Dictionary<Vector2, Texture2D> dictionary3 = DynamicHandSlicer.SliceSheet(texture2.Value, 4, 4);
					for (int i = 0; i < 4; i++)
					{
						dictionary3.TryGetValue(new Vector2(0f, (float)i), out var value2);
						Sprite replacementSprite = TextureCompositor.TextureToSprite(value2);
						string text = "";
						switch (i)
						{
						case 0:
							text = "interact-hand-open";
							break;
						case 1:
							text = "interact-hand-grabbed";
							break;
						case 2:
							text = "interact-hand-point";
							break;
						case 3:
							text = "interact-hand-item";
							break;
						}
						InteractSwap val5 = new InteractSwap
						{
							replacementSprite = replacementSprite,
							replacementSpriteName = text,
							spriteName = text
						};
						dictionary2.TryAdd(val5.spriteName, val5);
					}
				}
				Cosmetic_HandItem_Data cosmeticData = val.cosmeticData;
				if (cosmeticData.swapSprites == null)
				{
					cosmeticData.swapSprites = new List<SwapSprite>();
				}
				cosmeticData = val.cosmeticData;
				if (cosmeticData.interactSwaps == null)
				{
					cosmeticData.interactSwaps = new List<InteractSwap>();
				}
				foreach (string key2 in dictionary.Keys)
				{
					RHLog.Debug(key2, 368, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				}
				foreach (string key3 in dictionary2.Keys)
				{
					RHLog.Debug(key3, 373, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				}
				val.cosmeticData.swapSprites.AddRange(dictionary.Values);
				val.cosmeticData.interactSwaps.AddRange(dictionary2.Values);
				RHHands.Add((Cosmetic_Base)(object)val);
				SafeInitialize(val);
			}
		}

		private void SafeInitialize(Cosmetic_HandItem item)
		{
			if (!(typeof(Cosmetic_HandItem).GetField("swapDict", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(item) is IDictionary dictionary) || dictionary.Count == 0)
			{
				RHLog.Debug("Initializing " + ((Object)item).name + "...", 395, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
				InvokePrivateMethod(item, "Initialize");
			}
			else
			{
				RHLog.Warning(((Object)item).name + " was already initialized! Skipping to avoid Dictionary crash.", 400, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
			}
		}

		private void ApplyCosmetics()
		{
			if (!Object.op_Implicit((Object)(object)cosmeticsMenu) || RHHands.Count == 0)
			{
				return;
			}
			InjectIntoCosmeticManager();
			FieldInfo field = typeof(CosmeticPage).GetField("cosmetics", BindingFlags.Instance | BindingFlags.NonPublic);
			if (cosmeticPage != null && field != null)
			{
				List<Cosmetic_Base> list = new List<Cosmetic_Base>();
				list.AddRange(RHHands);
				field.SetValue(cosmeticPage, list);
			}
			try
			{
				cosmeticsMenu.FillCosmeticPage(RHHands, "Only RH", cosmeticPage);
			}
			catch (Exception ex)
			{
				RHLog.Error("FillCosmeticPage failed: " + ex.Message, 427, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
			}
		}

		public void InjectIntoCosmeticManager()
		{
			try
			{
				Type typeFromHandle = typeof(CL_CosmeticManager);
				FieldInfo field = typeFromHandle.GetField("cosmeticHands", BindingFlags.Static | BindingFlags.NonPublic);
				FieldInfo field2 = typeFromHandle.GetField("cosmeticHandDict", BindingFlags.Static | BindingFlags.NonPublic);
				FieldInfo field3 = typeFromHandle.GetField("loadedCosmetics", BindingFlags.Static | BindingFlags.NonPublic);
				List<Cosmetic_HandItem> list = (List<Cosmetic_HandItem>)field.GetValue(null);
				Dictionary<string, Cosmetic_HandItem> dictionary = (Dictionary<string, Cosmetic_HandItem>)field2.GetValue(null);
				List<Cosmetic_Base> list2 = (List<Cosmetic_Base>)field3.GetValue(null);
				foreach (Cosmetic_Base rHHand in RHHands)
				{
					Cosmetic_HandItem val = (Cosmetic_HandItem)(object)((rHHand is Cosmetic_HandItem) ? rHHand : null);
					if (!((Object)(object)val == (Object)null) && !dictionary.ContainsKey(((Cosmetic_Base)val).cosmeticInfo.id))
					{
						list.Add(val);
						dictionary.Add(((Cosmetic_Base)val).cosmeticInfo.id, val);
						list2.Add((Cosmetic_Base)(object)val);
						SettingsManager.settings.cosmeticSaveData.FillNewCosmeticInfo((Cosmetic_Base)(object)val);
						RHLog.Info("Successfully injected " + ((Object)val).name + " into CL_CosmeticManager", 463, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
					}
				}
			}
			catch (Exception ex)
			{
				RHLog.Error("Failed to inject into CL_CosmeticManager: " + ex.Message, 469, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
			}
		}

		public static void InvokePrivateMethod(object obj, string methodName, params object[] args)
		{
			MethodInfo method = obj.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				method.Invoke(obj, args);
			}
			else
			{
				RHLog.Error("Method '" + methodName + "' not found on " + obj.GetType().Name, 487, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/OF_CosmeticPage.cs");
			}
		}
	}
	public static class RHSettingsManager
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<UI_TabGroup, bool> <>9__4_0;

			public static UnityAction <>9__4_1;

			public static Action<ResourcePack> <>9__4_6;

			public static UnityAction <>9__4_2;

			public static Action<ResourcePack> <>9__4_7;

			public static UnityAction <>9__4_3;

			public static UnityAction <>9__4_4;

			internal bool <LoadCustomSettings_Internal>b__4_0(UI_TabGroup tabGroup)
			{
				return ((Object)tabGroup).name.ToLower() == "tab selection hor";
			}

			internal void <LoadCustomSettings_Internal>b__4_1()
			{
				Application.OpenURL("file://" + RHConfig.PacksFolder.Replace("\\", "/"));
			}

			internal void <LoadCustomSettings_Internal>b__4_2()
			{
				ResourcePacksManager.LoadedPacks.ForEach(delegate(ResourcePack p)
				{
					p.IsActive = true;
				});
				UI_RHPacksList.Instance?.ReloadPacks();
			}

			internal void <LoadCustomSettings_Internal>b__4_6(ResourcePack p)
			{
				p.IsActive = true;
			}

			internal void <LoadCustomSettings_Internal>b__4_3()
			{
				ResourcePacksManager.LoadedPacks.ForEach(delegate(ResourcePack p)
				{
					p.IsActive = false;
				});
				UI_RHPacksList.Instance?.ReloadPacks();
			}

			internal void <LoadCustomSettings_Internal>b__4_7(ResourcePack p)
			{
				p.IsActive = false;
			}

			internal void <LoadCustomSettings_Internal>b__4_4()
			{
				UI_RHPacksList.Instance?.ReloadPacks();
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass4_0
		{
			public UI_TabGroup tabGroup;

			internal void <LoadCustomSettings_Internal>b__5()
			{
				tabGroup.SelectTab("packs");
			}
		}

		[CompilerGenerated]
		private sealed class <LoadCustomSettings_Internal>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public UI_SettingsMenu settingsMenu;

			private <>c__DisplayClass4_0 <>8__1;

			private UI_TabGroup[] <tabGroups>5__2;

			private GameObject <button>5__3;

			private Button <buttonButton>5__4;

			private TextMeshProUGUI <buttonTmp>5__5;

			private GameObject <menu>5__6;

			private Transform <buttons>5__7;

			private Button <reloadButton>5__8;

			private Button <enableAllButton>5__9;

			private Button <disableAllButton>5__10;

			private Button <openFolder>5__11;

			private Tab <prevTab>5__12;

			private Tab <tab>5__13;

			private int <i>5__14;

			private Transform <child>5__15;

			private string <cName>5__16;

			private int <i>5__17;

			private Transform <child>5__18;

			private TextMeshProUGUI <title>5__19;

			private GameObject <copiedTitle>5__20;

			private TextMeshProUGUI <tmp>5__21;

			private TextMeshProUGUI[] <texts>5__22;

			private TextMeshProUGUI[] <>s__23;

			private int <>s__24;

			private TextMeshProUGUI <text>5__25;

			private Exception <e>5__26;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadCustomSettings_Internal>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<tabGroups>5__2 = null;
				<button>5__3 = null;
				<buttonButton>5__4 = null;
				<buttonTmp>5__5 = null;
				<menu>5__6 = null;
				<buttons>5__7 = null;
				<reloadButton>5__8 = null;
				<enableAllButton>5__9 = null;
				<disableAllButton>5__10 = null;
				<openFolder>5__11 = null;
				<prevTab>5__12 = null;
				<tab>5__13 = null;
				<child>5__15 = null;
				<cName>5__16 = null;
				<child>5__18 = null;
				<title>5__19 = null;
				<copiedTitle>5__20 = null;
				<tmp>5__21 = null;
				<texts>5__22 = null;
				<>s__23 = null;
				<text>5__25 = null;
				<e>5__26 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				//IL_020b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0210: Unknown result type (might be due to invalid IL or missing references)
				//IL_0216: Expected O, but got Unknown
				//IL_023b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0240: Unknown result type (might be due to invalid IL or missing references)
				//IL_0246: Expected O, but got Unknown
				//IL_026b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0270: Unknown result type (might be due to invalid IL or missing references)
				//IL_0276: Expected O, but got Unknown
				//IL_029b: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a6: Expected O, but got Unknown
				//IL_057a: Unknown result type (might be due to invalid IL or missing references)
				//IL_057f: Unknown result type (might be due to invalid IL or missing references)
				//IL_058b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0596: Unknown result type (might be due to invalid IL or missing references)
				//IL_05a7: Expected O, but got Unknown
				//IL_05be: Unknown result type (might be due to invalid IL or missing references)
				//IL_05c8: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSecondsRealtime(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					RHLog.Info("Loading custom settings menu...", 49, "/mnt/EXTRA_DATA/Modding Stuff/White Knuckle/ResourcefulHands/Source/Types/UI/SettingsManager.cs");
					if ((Object)(object)Plugin.Assets == (Object)null)